diff options
Diffstat (limited to 'src/main/java/com/gitblit/utils/JnaUtils.java')
-rw-r--r-- | src/main/java/com/gitblit/utils/JnaUtils.java | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/main/java/com/gitblit/utils/JnaUtils.java b/src/main/java/com/gitblit/utils/JnaUtils.java new file mode 100644 index 00000000..b7d7209f --- /dev/null +++ b/src/main/java/com/gitblit/utils/JnaUtils.java @@ -0,0 +1,226 @@ +/* + * Copyright 2013 gitblit.com. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.gitblit.utils; + +import com.sun.jna.Library; +import com.sun.jna.Native; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Collection of static methods to access native OS library functionality. + * + * @author Florian Zschocke + */ +public class JnaUtils { + public static final int S_IFMT = 0170000; + public static final int S_IFIFO = 0010000; + public static final int S_IFCHR = 0020000; + public static final int S_IFDIR = 0040000; + public static final int S_IFBLK = 0060000; + public static final int S_IFREG = 0100000; + public static final int S_IFLNK = 0120000; + public static final int S_IFSOCK = 0140000; + + public static final int S_ISUID = 0004000; + public static final int S_ISGID = 0002000; + public static final int S_ISVTX = 0001000; + + public static final int S_IRWXU = 0000700; + public static final int S_IRUSR = 0000400; + public static final int S_IWUSR = 0000200; + public static final int S_IXUSR = 0000100; + public static final int S_IRWXG = 0000070; + public static final int S_IRGRP = 0000040; + public static final int S_IWGRP = 0000020; + public static final int S_IXGRP = 0000010; + public static final int S_IRWXO = 0000007; + public static final int S_IROTH = 0000004; + public static final int S_IWOTH = 0000002; + public static final int S_IXOTH = 0000001; + + + private static final Logger LOGGER = LoggerFactory.getLogger(JGitUtils.class); + + private static UnixCLibrary unixlibc = null; + + + public static boolean isWindows() + { + return System.getProperty("os.name").toLowerCase().startsWith("windows"); + } + + + private interface UnixCLibrary extends Library { + public int chmod(String path, int mode); + } + + + public static int setFilemode(File path, int mode) + { + return setFilemode(path.getAbsolutePath(), mode); + } + + public static int setFilemode(String path, int mode) + { + if (isWindows()) { + throw new UnsupportedOperationException("The method JnaUtils.getFilemode is not supported under Windows."); + } + + return getUnixCLibrary().chmod(path, mode); + } + + + + public static int getFilemode(File path) + { + return getFilemode(path.getAbsolutePath()); + } + + public static int getFilemode(String path) + { + if (isWindows()) { + throw new UnsupportedOperationException("The method JnaUtils.getFilemode is not supported under Windows."); + } + + + int mode = 0; + + // Use a Runtime, because implementing stat() via JNA is just too much trouble. + String lsLine = runProcessLs(path); + if (lsLine == null) { + LOGGER.debug("Could not get file information for path " + path); + return -1; + } + + Pattern p = Pattern.compile("^(([-bcdlsp])([-r][-w][-xSs])([-r][-w][-xSs])([-r][-w][-xTt])) "); + Matcher m = p.matcher(lsLine); + if ( !m.lookingAt() ) { + LOGGER.debug("Could not parse valid file mode information for path " + path); + return -1; + } + + // Parse mode string to mode bits + String group = m.group(2); + switch (group.charAt(0)) { + case 'p' : + mode |= 0010000; break; + case 'c': + mode |= 0020000; break; + case 'd': + mode |= 0040000; break; + case 'b': + mode |= 0060000; break; + case '-': + mode |= 0100000; break; + case 'l': + mode |= 0120000; break; + case 's': + mode |= 0140000; break; + } + + for ( int i = 0; i < 3; i++) { + group = m.group(3 + i); + switch (group.charAt(0)) { + case 'r': + mode |= (0400 >> i*3); break; + case '-': + break; + } + + switch (group.charAt(1)) { + case 'w': + mode |= (0200 >> i*3); break; + case '-': + break; + } + + switch (group.charAt(2)) { + case 'x': + mode |= (0100 >> i*3); break; + case 'S': + mode |= (04000 >> i); break; + case 's': + mode |= (0100 >> i*3); + mode |= (04000 >> i); break; + case 'T': + mode |= 01000; break; + case 't': + mode |= (0100 >> i*3); + mode |= 01000; break; + case '-': + break; + } + } + + return mode; + } + + + private static String runProcessLs(String path) + { + String cmd = "ls -ldO " + path; + Runtime rt = Runtime.getRuntime(); + Process pr = null; + InputStreamReader ir = null; + BufferedReader br = null; + String output = null; + + try { + pr = rt.exec(cmd); + ir = new InputStreamReader(pr.getInputStream()); + br = new BufferedReader(ir); + + output = br.readLine(); + + while (br.readLine() != null) ; // Swallow remaining output + } + catch (IOException e) { + LOGGER.debug("Exception while running unix command '" + cmd + "': " + e); + } + finally { + if (pr != null) try { pr.waitFor(); } catch (Exception ignored) {} + + if (br != null) try { br.close(); } catch (Exception ignored) {} + if (ir != null) try { ir.close(); } catch (Exception ignored) {} + + if (pr != null) try { pr.getOutputStream().close(); } catch (Exception ignored) {} + if (pr != null) try { pr.getInputStream().close(); } catch (Exception ignored) {} + if (pr != null) try { pr.getErrorStream().close(); } catch (Exception ignored) {} + } + + return output; + } + + + private static UnixCLibrary getUnixCLibrary() + { + if (unixlibc == null) { + unixlibc = (UnixCLibrary) Native.loadLibrary("c", UnixCLibrary.class); + if (unixlibc == null) throw new RuntimeException("Could not initialize native C library."); + } + return unixlibc; + } + +} |