package com.lody.virtual.helper.utils; import android.os.Build; import android.os.Parcel; import android.system.Os; import android.text.TextUtils; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @author Lody */ public class FileUtils { /** * @param path * @param mode {@link FileMode} * @throws Exception */ public static void chmod(String path, int mode) throws Exception { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { try { Os.chmod(path, mode); return; } catch (Exception e) { e.printStackTrace(); } } File file = new File(path); String cmd = "chmod "; if (file.isDirectory()) { cmd += " -R "; } String cmode = String.format("%o", mode); Runtime.getRuntime().exec(cmd + cmode + " " + path).waitFor(); } public static void createSymlink(String oldPath, String newPath) throws Exception { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Os.symlink(oldPath, newPath); } else { Runtime.getRuntime().exec("ln -s " + oldPath + " " + newPath).waitFor(); } } public static boolean isSymlink(File file) throws IOException { if (file == null) throw new NullPointerException("File must not be null"); File canon; if (file.getParent() == null) { canon = file; } else { File canonDir = file.getParentFile().getCanonicalFile(); canon = new File(canonDir, file.getName()); } return !canon.getCanonicalFile().equals(canon.getAbsoluteFile()); } public static void writeParcelToFile(Parcel p, File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); fos.write(p.marshall()); fos.close(); } public static byte[] toByteArray(InputStream inStream) throws IOException { ByteArrayOutputStream swapStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; int rc; while ((rc = inStream.read(buff, 0, 100)) > 0) { swapStream.write(buff, 0, rc); } return swapStream.toByteArray(); } public static boolean deleteDir(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (String file : children) { boolean success = deleteDir(new File(dir, file)); if (!success) { return false; } } } return dir.delete(); } public static boolean deleteDir(String dir) { return deleteDir(new File(dir)); } public static void writeToFile(InputStream dataIns, File target) throws IOException { final int BUFFER = 1024; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(target)); int count; byte data[] = new byte[BUFFER]; while ((count = dataIns.read(data, 0, BUFFER)) != -1) { bos.write(data, 0, count); } bos.close(); } public static void writeToFile(byte[] data, File target) throws IOException { FileOutputStream fo = null; ReadableByteChannel src = null; FileChannel out = null; try { src = Channels.newChannel(new ByteArrayInputStream(data)); fo = new FileOutputStream(target); out = fo.getChannel(); out.transferFrom(src, 0, data.length); } finally { if (fo != null) { fo.close(); } if (src != null) { src.close(); } if (out != null) { out.close(); } } } public static void copyFile(File source, File target) throws IOException { FileInputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = new FileInputStream(source); outputStream = new FileOutputStream(target); FileChannel iChannel = inputStream.getChannel(); FileChannel oChannel = outputStream.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { buffer.clear(); int r = iChannel.read(buffer); if (r == -1) break; buffer.limit(buffer.position()); buffer.position(0); oChannel.write(buffer); } } finally { closeQuietly(inputStream); closeQuietly(outputStream); } } public static void closeQuietly(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception ignored) { } } } public static int peekInt(byte[] bytes, int value, ByteOrder endian) { int v2; int v0; if (endian == ByteOrder.BIG_ENDIAN) { v0 = value + 1; v2 = v0 + 1; v0 = (bytes[v0] & 255) << 16 | (bytes[value] & 255) << 24 | (bytes[v2] & 255) << 8 | bytes[v2 + 1] & 255; } else { v0 = value + 1; v2 = v0 + 1; v0 = (bytes[v0] & 255) << 8 | bytes[value] & 255 | (bytes[v2] & 255) << 16 | (bytes[v2 + 1] & 255) << 24; } return v0; } private static boolean isValidExtFilenameChar(char c) { switch (c) { case '\0': case '/': return false; default: return true; } } /** * Check if given filename is valid for an ext4 filesystem. */ public static boolean isValidExtFilename(String name) { return (name != null) && name.equals(buildValidExtFilename(name)); } /** * Mutate the given filename to make it valid for an ext4 filesystem, * replacing any invalid characters with "_". */ public static String buildValidExtFilename(String name) { if (TextUtils.isEmpty(name) || ".".equals(name) || "..".equals(name)) { return "(invalid)"; } final StringBuilder res = new StringBuilder(name.length()); for (int i = 0; i < name.length(); i++) { final char c = name.charAt(i); if (isValidExtFilenameChar(c)) { res.append(c); } else { res.append('_'); } } return res.toString(); } public interface FileMode { int MODE_ISUID = 04000; int MODE_ISGID = 02000; int MODE_ISVTX = 01000; int MODE_IRUSR = 00400; int MODE_IWUSR = 00200; int MODE_IXUSR = 00100; int MODE_IRGRP = 00040; int MODE_IWGRP = 00020; int MODE_IXGRP = 00010; int MODE_IROTH = 00004; int MODE_IWOTH = 00002; int MODE_IXOTH = 00001; int MODE_755 = MODE_IRUSR | MODE_IWUSR | MODE_IXUSR | MODE_IRGRP | MODE_IXGRP | MODE_IROTH | MODE_IXOTH; } /** * Lock the specified fle */ public static class FileLock { private static FileLock singleton; private Map<String, FileLockCount> mRefCountMap = new ConcurrentHashMap<String, FileLockCount>(); public static FileLock getInstance() { if (singleton == null) { singleton = new FileLock(); } return singleton; } private int RefCntInc(String filePath, java.nio.channels.FileLock fileLock, RandomAccessFile randomAccessFile, FileChannel fileChannel) { int refCount; if (this.mRefCountMap.containsKey(filePath)) { FileLockCount fileLockCount = this.mRefCountMap.get(filePath); int i = fileLockCount.mRefCount; fileLockCount.mRefCount = i + 1; refCount = i; } else { refCount = 1; this.mRefCountMap.put(filePath, new FileLockCount(fileLock, refCount, randomAccessFile, fileChannel)); } return refCount; } private int RefCntDec(String filePath) { int refCount = 0; if (this.mRefCountMap.containsKey(filePath)) { FileLockCount fileLockCount = this.mRefCountMap.get(filePath); int i = fileLockCount.mRefCount - 1; fileLockCount.mRefCount = i; refCount = i; if (refCount <= 0) { this.mRefCountMap.remove(filePath); } } return refCount; } public boolean LockExclusive(File targetFile) { if (targetFile == null) { return false; } try { File lockFile = new File(targetFile.getParentFile().getAbsolutePath().concat("/lock")); if (!lockFile.exists()) { lockFile.createNewFile(); } RandomAccessFile randomAccessFile = new RandomAccessFile(lockFile.getAbsolutePath(), "rw"); FileChannel channel = randomAccessFile.getChannel(); java.nio.channels.FileLock lock = channel.lock(); if (!lock.isValid()) { return false; } RefCntInc(lockFile.getAbsolutePath(), lock, randomAccessFile, channel); return true; } catch (Exception e) { return false; } } /** * unlock odex file **/ public void unLock(File targetFile) { File lockFile = new File(targetFile.getParentFile().getAbsolutePath().concat("/lock")); if (!lockFile.exists()) { return; } if (this.mRefCountMap.containsKey(lockFile.getAbsolutePath())) { FileLockCount fileLockCount = this.mRefCountMap.get(lockFile.getAbsolutePath()); if (fileLockCount != null) { java.nio.channels.FileLock fileLock = fileLockCount.mFileLock; RandomAccessFile randomAccessFile = fileLockCount.fOs; FileChannel fileChannel = fileLockCount.fChannel; try { if (RefCntDec(lockFile.getAbsolutePath()) <= 0) { if (fileLock != null && fileLock.isValid()) { fileLock.release(); } if (randomAccessFile != null) { randomAccessFile.close(); } if (fileChannel != null) { fileChannel.close(); } } } catch (IOException e) { e.printStackTrace(); } } } } private class FileLockCount { FileChannel fChannel; RandomAccessFile fOs; java.nio.channels.FileLock mFileLock; int mRefCount; FileLockCount(java.nio.channels.FileLock fileLock, int mRefCount, RandomAccessFile fOs, FileChannel fChannel) { this.mFileLock = fileLock; this.mRefCount = mRefCount; this.fOs = fOs; this.fChannel = fChannel; } } } }