Commit f53fc03c authored by Skylot's avatar Skylot

core: use dynamic check for filesystem case-sensitivity (#158)

parent 9278c510
...@@ -4,7 +4,7 @@ dependencies { ...@@ -4,7 +4,7 @@ dependencies {
runtime files(jadxClasspath) runtime files(jadxClasspath)
compile files('lib/dx-1.13.jar') compile files('lib/dx-1.13.jar')
compile 'commons-io:commons-io:2.4' compile 'commons-io:commons-io:2.6'
compile 'org.ow2.asm:asm:5.0.3' compile 'org.ow2.asm:asm:5.0.3'
compile 'com.intellij:annotations:12.0' compile 'com.intellij:annotations:12.0'
compile 'uk.com.robust-it:cloning:1.9.2' compile 'uk.com.robust-it:cloning:1.9.2'
......
package jadx.core.dex.visitors; package jadx.core.dex.visitors;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.FilenameUtils;
import jadx.api.IJadxArgs; import jadx.api.IJadxArgs;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.codegen.TypeGen; import jadx.core.codegen.TypeGen;
...@@ -15,20 +22,11 @@ import jadx.core.dex.nodes.FieldNode; ...@@ -15,20 +22,11 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.FileUtils;
import jadx.core.utils.files.InputFile; import jadx.core.utils.files.InputFile;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;
public class RenameVisitor extends AbstractVisitor { public class RenameVisitor extends AbstractVisitor {
private static final boolean CASE_SENSITIVE_FS = IOCase.SYSTEM.isCaseSensitive();
private Deobfuscator deobfuscator; private Deobfuscator deobfuscator;
@Override @Override
...@@ -36,7 +34,7 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -36,7 +34,7 @@ public class RenameVisitor extends AbstractVisitor {
IJadxArgs args = root.getArgs(); IJadxArgs args = root.getArgs();
List<DexNode> dexNodes = root.getDexNodes(); List<DexNode> dexNodes = root.getDexNodes();
if (dexNodes.size() == 0) { if (dexNodes.isEmpty()) {
return; return;
} }
InputFile firstInputFile = dexNodes.get(0).getDexFile().getInputFile(); InputFile firstInputFile = dexNodes.get(0).getDexFile().getInputFile();
...@@ -50,7 +48,8 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -50,7 +48,8 @@ public class RenameVisitor extends AbstractVisitor {
if (deobfuscationOn) { if (deobfuscationOn) {
deobfuscator.execute(); deobfuscator.execute();
} }
checkClasses(root); boolean isCaseSensitive = FileUtils.isCaseSensitiveFS(new File(inputPath)); // args.getOutDir() - not set in gui
checkClasses(root, isCaseSensitive);
} }
@Override @Override
...@@ -63,11 +62,11 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -63,11 +62,11 @@ public class RenameVisitor extends AbstractVisitor {
return false; return false;
} }
private void checkClasses(RootNode root) { private void checkClasses(RootNode root, boolean caseSensitive) {
Set<String> clsNames = new HashSet<>(); Set<String> clsNames = new HashSet<>();
for (ClassNode cls : root.getClasses(true)) { for (ClassNode cls : root.getClasses(true)) {
checkClassName(cls); checkClassName(cls);
if (!CASE_SENSITIVE_FS) { if (!caseSensitive) {
ClassInfo classInfo = cls.getClassInfo(); ClassInfo classInfo = cls.getClassInfo();
String clsFileName = classInfo.getAlias().getFullPath(); String clsFileName = classInfo.getAlias().getFullPath();
if (!clsNames.add(clsFileName.toLowerCase())) { if (!clsNames.add(clsFileName.toLowerCase())) {
......
...@@ -40,8 +40,8 @@ public class ExportGradleProject { ...@@ -40,8 +40,8 @@ public class ExportGradleProject {
public void init() { public void init() {
try { try {
FileUtils.makeDirsForFile(srcOutDir); FileUtils.makeDirs(srcOutDir);
FileUtils.makeDirsForFile(resOutDir); FileUtils.makeDirs(resOutDir);
saveBuildGradle(); saveBuildGradle();
skipGeneratedClasses(); skipGeneratedClasses();
} catch (Exception e) { } catch (Exception e) {
......
package jadx.core.utils.files; package jadx.core.utils.files;
import jadx.core.utils.exceptions.JadxRuntimeException;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
...@@ -18,10 +16,14 @@ import java.util.jar.JarOutputStream; ...@@ -18,10 +16,14 @@ import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import org.apache.commons.io.IOCase;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import jadx.core.utils.exceptions.JadxRuntimeException;
public class FileUtils { public class FileUtils {
private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class); private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class);
...@@ -43,15 +45,22 @@ public class FileUtils { ...@@ -43,15 +45,22 @@ public class FileUtils {
} }
public static void makeDirsForFile(File file) { public static void makeDirsForFile(File file) {
File dir = file.getParentFile(); if (file != null) {
if (dir != null && !dir.exists()) { makeDirs(file.getParentFile());
// if directory already created in other thread mkdirs will return false, }
// so check dir existence again }
if (!dir.mkdirs() && !dir.exists()) {
private static final Object MKDIR_SYNC = new Object();
public static void makeDirs(@Nullable File dir) {
if (dir != null) {
synchronized (MKDIR_SYNC) {
if (!dir.exists() && !dir.mkdirs()) {
throw new JadxRuntimeException("Can't create directory " + dir); throw new JadxRuntimeException("Can't create directory " + dir);
} }
} }
} }
}
public static File createTempFile(String suffix) { public static File createTempFile(String suffix) {
File temp; File temp;
...@@ -186,4 +195,32 @@ public class FileUtils { ...@@ -186,4 +195,32 @@ public class FileUtils {
} }
} }
} }
public static boolean isCaseSensitiveFS(File testDir) {
if (testDir != null) {
File caseCheckUpper = new File(testDir, "CaseCheck");
File caseCheckLow = new File(testDir, "casecheck");
try {
makeDirs(testDir);
if (caseCheckUpper.createNewFile()) {
boolean caseSensitive = !caseCheckLow.exists();
LOG.debug("Filesystem at {} is {} case-sensitive", testDir.getAbsolutePath(),
(caseSensitive ? "" : "NOT"));
return caseSensitive;
} else {
LOG.debug("Failed to create file: {}", caseCheckUpper.getAbsolutePath());
}
} catch (Exception e) {
LOG.debug("Failed to detect filesystem case-sensitivity by file creation", e);
} finally {
try {
caseCheckUpper.delete();
caseCheckLow.delete();
} catch (Exception e) {
// ignore
}
}
}
return IOCase.SYSTEM.isCaseSensitive();
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment