/*
* ====================================================================
* Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package org.tmatesoft.svn.core.internal.util.jna;
import com.sun.jna.Memory;
import org.tmatesoft.svn.core.internal.wc.SVNFileType;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.util.SVNDebugLog;
import org.tmatesoft.svn.util.SVNLogType;
import java.io.File;
/**
* @version 1.3
* @author TMate Software Ltd.
*/
public class SVNLinuxUtil {
private static Memory ourSharedMemory;
private static final boolean ourIsDashStat = Boolean.getBoolean("svnkit.jna.dash_stat");
static {
try {
ourSharedMemory = new Memory(1024);
} catch (Throwable th) {
ourSharedMemory = null;
}
}
public static SVNFileType getFileType(File file) {
if (file == null || ourSharedMemory == null) {
return null;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return null;
}
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._lstat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.lstat(path, ourSharedMemory) :
cLibrary.__lxstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
if (file.exists() || file.isDirectory() || file.isFile()) {
return null;
}
return SVNFileType.NONE;
}
int mode = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris ?
ourSharedMemory.getShort(getFileModeOffset()) : ourSharedMemory.getInt(getFileModeOffset());
int type = mode & 0170000;
if (type == 0120000) {
return SVNFileType.SYMLINK;
} else if (type == 0040000) {
return SVNFileType.DIRECTORY;
} else if (type == 0100000) {
return SVNFileType.FILE;
} else {
if (file.exists() || file.isDirectory() || file.isFile()) {
return null;
}
return SVNFileType.NONE;
}
}
} catch (Throwable th) {
SVNDebugLog.getDefaultLog().logFine(SVNLogType.DEFAULT, th);
//
}
return null;
}
public static Boolean isExecutable(File file) {
if (file == null || ourSharedMemory == null) {
return null;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return null;
}
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._lstat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.lstat(path, ourSharedMemory) :
cLibrary.__lxstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
return null;
}
int mode = ourSharedMemory.getInt(getFileModeOffset());
int fuid = ourSharedMemory.getInt(getFileUserIDOffset());
int fgid = ourSharedMemory.getInt(getFileGroupIDOffset());
int access = mode & 0777;
int mask = 0111;
if (JNALibraryLoader.getUID() == fuid) {
mask = 0100; // check user
} else if (JNALibraryLoader.getGID() == fgid) {
mask = 0010; // check group
} else {
mask = 0001; // check other.
}
return Boolean.valueOf((access & mask) != 0);
}
} catch (Throwable th) {
//
}
return null;
}
public static String getLinkTarget(File file) {
if (file == null || ourSharedMemory == null) {
return null;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return null;
}
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
rc = cLibrary.readlink(path, ourSharedMemory, 1024);
}
if (rc <= 0) {
return null;
}
byte[] buffer = new byte[rc];
ourSharedMemory.read(0, buffer, 0, rc);
// intentionally read in system default encoding.
return new String(buffer, 0, rc);
}
} catch (Throwable th) {
//
}
return null;
}
public static Long getSymlinkLastModified(File file) {
if (file == null || ourSharedMemory == null) {
return null;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return null;
}
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._lstat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.lstat(path, ourSharedMemory) :
cLibrary.__lxstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
return null;
}
return ourSharedMemory.getLong(getFileLastModifiedOffset()) * 1000;
}
} catch (Throwable th) {
//
}
return null;
}
public static boolean setExecutable(File file, boolean set) {
if (file == null || ourSharedMemory == null) {
return false;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return false;
}
SVNDebugLog.getDefaultLog().logFine(SVNLogType.DEFAULT, "Calling JNA.setExecutable");
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._lstat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.lstat(path, ourSharedMemory) :
cLibrary.__lxstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
return false;
}
int mode = ourSharedMemory.getInt(getFileModeOffset());
int access = mode & 0777;
int perms = access;
if (set) {
if ((access & 0400) != 0)
perms |= 0100;
if ((access & 0040) != 0)
perms |= 0010;
if ((access & 0004) != 0)
perms |= 0001;
} else {
if ((access & 0400) != 0)
perms &= ~0100;
if ((access & 0040) != 0)
perms &= ~0010;
if ((access & 0004) != 0)
perms &= ~0001;
}
synchronized (cLibrary) {
rc = cLibrary.chmod(path, perms);
}
return rc < 0 ? false : true;
}
} catch (Throwable th) {
//
}
return false;
}
public static boolean setWritable(File file) {
if (file == null || ourSharedMemory == null) {
return false;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return false;
}
SVNDebugLog.getDefaultLog().logFine(SVNLogType.DEFAULT, "Calling JNA.setWritable");
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._lstat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.lstat(path, ourSharedMemory) :
cLibrary.__lxstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
return false;
}
int mode = ourSharedMemory.getInt(getFileModeOffset());
int access = mode & 0777;
int mask = 0;
if ((access & 0400) != 0) {
mask |= 0200;
}
if ((access & 0040) != 0) {
mask |= 0020;
}
if ((access & 0004) != 0) {
mask |= 0002;
}
if (mask == 0) {
return false;
}
synchronized (cLibrary) {
rc = cLibrary.chmod(path, mask | access);
}
return rc < 0 ? false : true;
}
} catch (Throwable th) {
//
}
return false;
}
public static boolean setSGID(File file) {
if (file == null || ourSharedMemory == null) {
return false;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return false;
}
synchronized (ourSharedMemory) {
ourSharedMemory.clear();
int rc;
synchronized (cLibrary) {
if (ourIsDashStat && SVNFileUtil.isBSD) {
rc = cLibrary._stat(path, ourSharedMemory);
} else {
rc = SVNFileUtil.isOSX || SVNFileUtil.isBSD || SVNFileUtil.isSolaris || (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) ?
cLibrary.stat(path, ourSharedMemory) :
cLibrary.__xstat64(0, path, ourSharedMemory);
}
}
if (rc < 0) {
return false;
}
int mode = ourSharedMemory.getInt(getFileModeOffset());
int access = mode & 07777;
int mask = 02000;
if ((access & mask) != 0) {
return false;
}
synchronized (cLibrary) {
rc = cLibrary.chmod(path, mask | access);
}
return rc < 0 ? false : true;
}
} catch (Throwable th) {
//
}
return false;
}
public static boolean createSymlink(File file, String linkName) {
if (file == null || linkName == null || ourSharedMemory == null) {
return false;
}
String path = file.getAbsolutePath();
if (path.endsWith("/") && path.length() > 1) {
path = path.substring(0, path.length() - 1);
}
try {
ISVNCLibrary cLibrary = JNALibraryLoader.getCLibrary();
if (cLibrary == null) {
return false;
}
int rc;
synchronized (cLibrary) {
rc = cLibrary.symlink(linkName, path);
}
return rc < 0 ? false : true;
} catch (Throwable th) {
//
}
return false;
}
private static int getFileModeOffset() {
if (SVNFileUtil.isLinux && SVNFileUtil.is64Bit) {
return 24;
}
if (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) {
return 16;
}
if (SVNFileUtil.isOSX) {
return 8;
}
if (SVNFileUtil.isSolaris && SVNFileUtil.is64Bit) {
return 16;
}
if (SVNFileUtil.isSolaris && SVNFileUtil.is32Bit) {
return 20;
}
if (SVNFileUtil.isBSD) {
return 8;
}
return 16;
}
private static int getFileUserIDOffset() {
int modeOffset = getFileModeOffset();
if (SVNFileUtil.isLinux && SVNFileUtil.is64Bit) {
return modeOffset + 4;
}
if (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) {
return modeOffset + 8;
}
if (SVNFileUtil.isOSX) {
return modeOffset + 4;
}
if (SVNFileUtil.isSolaris) {
return modeOffset + 8;
}
if (SVNFileUtil.isBSD) {
return modeOffset + 4;
}
return modeOffset + 8;
}
private static int getFileGroupIDOffset() {
return getFileUserIDOffset() + 4;
}
private static int getFileLastModifiedOffset() {
if (SVNFileUtil.isLinux && SVNFileUtil.is64Bit) {
return 88;
}
if (SVNFileUtil.isLinux && SVNFileUtil.is32Bit) {
return 64;
}
if (SVNFileUtil.isBSD) {
return 32;
}
if (SVNFileUtil.isSolaris) {
//64bit
return 64;
}
if (SVNFileUtil.isOSX) {
return 48;
}
return 88;
}
}