/* * ==================================================================== * 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; } }