summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/gitblit/utils/JnaUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/gitblit/utils/JnaUtils.java')
-rw-r--r--src/main/java/com/gitblit/utils/JnaUtils.java226
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;
+ }
+
+}