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;
}
}
}
}