| package jnr.posix.util; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| /** |
| * Honor semantics of chmod as best we can in pure Java. Note, this uses reflection to be |
| * more tolerant of different Java versions. |
| */ |
| public class Chmod { |
| private static final boolean CHMOD_API_AVAILABLE; |
| private static final Method setWritable; |
| private static final Method setReadable; |
| private static final Method setExecutable; |
| |
| static { |
| boolean apiAvailable = false; |
| Method setWritableVar = null; |
| Method setReadableVar = null; |
| Method setExecutableVar = null; |
| try { |
| setWritableVar = File.class.getMethod("setWritable", new Class[] {Boolean.TYPE, Boolean.TYPE}); |
| setReadableVar = File.class.getMethod("setReadable", new Class[] {Boolean.TYPE, Boolean.TYPE}); |
| setExecutableVar = File.class.getMethod("setExecutable", new Class[] {Boolean.TYPE, Boolean.TYPE}); |
| apiAvailable = true; |
| } catch (Exception e) { |
| // failed to load methods, no chmod API available |
| } |
| setWritable = setWritableVar; |
| setReadable = setReadableVar; |
| setExecutable = setExecutableVar; |
| CHMOD_API_AVAILABLE = apiAvailable; |
| } |
| |
| public static int chmod(File file, String mode) { |
| if (CHMOD_API_AVAILABLE) { |
| // fast version |
| char other = '0'; |
| if (mode.length() >= 1) { |
| other = mode.charAt(mode.length() - 1); |
| } |
| //char group = mode.charAt(mode.length() - 2); |
| char user = '0'; |
| if (mode.length() >= 3) { |
| user = mode.charAt(mode.length() - 3); |
| } |
| //char setuidgid = mode.charAt(mode.length() - 3); |
| |
| // group and setuid/gid are ignored, no way to do them fast. Should we fall back on slow? |
| if (!setPermissions(file, other, false)) return -1; |
| if (!setPermissions(file, user, true)) return -1; |
| return 0; |
| } else { |
| // slow version |
| try { |
| Process chmod = Runtime.getRuntime().exec("/bin/chmod " + mode + " " + file.getAbsolutePath()); |
| chmod.waitFor(); |
| return chmod.exitValue(); |
| } catch (IOException ioe) { |
| // FIXME: ignore? |
| } catch (InterruptedException ie) { |
| Thread.currentThread().interrupt(); |
| } |
| } |
| return -1; |
| } |
| |
| private static boolean setPermissions(File file, char permChar, boolean userOnly) { |
| int permValue = Character.digit(permChar, 8); |
| |
| try { |
| if ((permValue & 1) != 0) { |
| setExecutable.invoke(file, new Object[] {Boolean.TRUE, Boolean.valueOf(userOnly)}); |
| } else { |
| setExecutable.invoke(file, new Object[] {Boolean.FALSE, Boolean.valueOf(userOnly)}); |
| } |
| |
| if ((permValue & 2) != 0) { |
| setWritable.invoke(file, new Object[] {Boolean.TRUE, Boolean.valueOf(userOnly)}); |
| } else { |
| setWritable.invoke(file, new Object[] {Boolean.FALSE, Boolean.valueOf(userOnly)}); |
| } |
| |
| if ((permValue & 4) != 0) { |
| setReadable.invoke(file, new Object[] {Boolean.TRUE, Boolean.valueOf(userOnly)}); |
| } else { |
| setReadable.invoke(file, new Object[] {Boolean.FALSE, Boolean.valueOf(userOnly)}); |
| } |
| |
| return true; |
| } catch (IllegalAccessException iae) { |
| // ignore, return false below |
| } catch (InvocationTargetException ite) { |
| // ignore, return false below |
| } |
| |
| return false; |
| } |
| } |