core: use dynamic check for filesystem case-sensitivity (#158)
This commit is contained in:
@@ -4,7 +4,7 @@ dependencies {
|
||||
runtime files(jadxClasspath)
|
||||
|
||||
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 'com.intellij:annotations:12.0'
|
||||
compile 'uk.com.robust-it:cloning:1.9.2'
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
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.core.Consts;
|
||||
import jadx.core.codegen.TypeGen;
|
||||
@@ -15,20 +22,11 @@ import jadx.core.dex.nodes.FieldNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
import jadx.core.utils.files.FileUtils;
|
||||
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 {
|
||||
|
||||
private static final boolean CASE_SENSITIVE_FS = IOCase.SYSTEM.isCaseSensitive();
|
||||
|
||||
private Deobfuscator deobfuscator;
|
||||
|
||||
@Override
|
||||
@@ -36,7 +34,7 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
IJadxArgs args = root.getArgs();
|
||||
|
||||
List<DexNode> dexNodes = root.getDexNodes();
|
||||
if (dexNodes.size() == 0) {
|
||||
if (dexNodes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
InputFile firstInputFile = dexNodes.get(0).getDexFile().getInputFile();
|
||||
@@ -50,7 +48,8 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
if (deobfuscationOn) {
|
||||
deobfuscator.execute();
|
||||
}
|
||||
checkClasses(root);
|
||||
boolean isCaseSensitive = FileUtils.isCaseSensitiveFS(new File(inputPath)); // args.getOutDir() - not set in gui
|
||||
checkClasses(root, isCaseSensitive);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,11 +62,11 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void checkClasses(RootNode root) {
|
||||
private void checkClasses(RootNode root, boolean caseSensitive) {
|
||||
Set<String> clsNames = new HashSet<>();
|
||||
for (ClassNode cls : root.getClasses(true)) {
|
||||
checkClassName(cls);
|
||||
if (!CASE_SENSITIVE_FS) {
|
||||
if (!caseSensitive) {
|
||||
ClassInfo classInfo = cls.getClassInfo();
|
||||
String clsFileName = classInfo.getAlias().getFullPath();
|
||||
if (!clsNames.add(clsFileName.toLowerCase())) {
|
||||
|
||||
@@ -40,8 +40,8 @@ public class ExportGradleProject {
|
||||
|
||||
public void init() {
|
||||
try {
|
||||
FileUtils.makeDirsForFile(srcOutDir);
|
||||
FileUtils.makeDirsForFile(resOutDir);
|
||||
FileUtils.makeDirs(srcOutDir);
|
||||
FileUtils.makeDirs(resOutDir);
|
||||
saveBuildGradle();
|
||||
skipGeneratedClasses();
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package jadx.core.utils.files;
|
||||
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
@@ -18,10 +16,14 @@ import java.util.jar.JarOutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.commons.io.IOCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public class FileUtils {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FileUtils.class);
|
||||
|
||||
@@ -43,12 +45,19 @@ public class FileUtils {
|
||||
}
|
||||
|
||||
public static void makeDirsForFile(File file) {
|
||||
File dir = file.getParentFile();
|
||||
if (dir != null && !dir.exists()) {
|
||||
// if directory already created in other thread mkdirs will return false,
|
||||
// so check dir existence again
|
||||
if (!dir.mkdirs() && !dir.exists()) {
|
||||
throw new JadxRuntimeException("Can't create directory " + dir);
|
||||
if (file != null) {
|
||||
makeDirs(file.getParentFile());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user