static StatFileHelper() { StatMethod = null; // Try to load the Mono Posix assembly. If it doesn't exist, we're on Windows. Assembly MonoPosix; try { MonoPosix = Assembly.Load("Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); } catch (FileNotFoundException) { return; } Type SyscallType = MonoPosix.GetType("Mono.Unix.Native.Syscall"); if (SyscallType == null) { throw new InvalidOperationException("Couldn't find Syscall type"); } StatMethod = SyscallType.GetMethod("stat"); if (StatMethod == null) { throw new InvalidOperationException("Couldn't find Mono.Unix.Native.Syscall.stat method"); } Type StatType = MonoPosix.GetType("Mono.Unix.Native.Stat"); if (StatType == null) { throw new InvalidOperationException("Couldn't find Mono.Unix.Native.Stat type"); } StatModeField = StatType.GetField("st_mode"); if (StatModeField == null) { throw new InvalidOperationException("Couldn't find Mono.Unix.Native.Stat.st_mode field"); } }
static bool SetExecutablePermissions(string RootDir, IEnumerable <DependencyFile> Files) { // Try to load the Mono Posix assembly. If it doesn't exist, we're on Windows. Assembly MonoPosix; try { MonoPosix = Assembly.Load("Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756"); } catch (FileNotFoundException) { return(true); } // Dynamically find all the types and methods for Syscall.stat and Syscall.chmod Type SyscallType = MonoPosix.GetType("Mono.Unix.Native.Syscall"); if (SyscallType == null) { Log.WriteError("Couldn't find Syscall type"); return(false); } MethodInfo StatMethod = SyscallType.GetMethod("stat"); if (StatMethod == null) { Log.WriteError("Couldn't find Mono.Unix.Native.Syscall.stat method"); return(false); } MethodInfo ChmodMethod = SyscallType.GetMethod("chmod"); if (ChmodMethod == null) { Log.WriteError("Couldn't find Mono.Unix.Native.Syscall.chmod method"); return(false); } Type StatType = MonoPosix.GetType("Mono.Unix.Native.Stat"); if (StatType == null) { Log.WriteError("Couldn't find Mono.Unix.Native.Stat type"); return(false); } FieldInfo StatModeField = StatType.GetField("st_mode"); if (StatModeField == null) { Log.WriteError("Couldn't find Mono.Unix.Native.Stat.st_mode field"); return(false); } // Update all the executable permissions const uint ExecutableBits = (1 << 0) | (1 << 3) | (1 << 6); foreach (DependencyFile File in Files) { if (File.IsExecutable) { string FileName = Path.Combine(RootDir, File.Name); // Call Syscall.stat(Filename, out Stat) object[] StatArgs = new object[] { FileName, null }; int StatResult = (int)StatMethod.Invoke(null, StatArgs); if (StatResult != 0) { Log.WriteError("Stat() call for {0} failed with error {1}", File.Name, StatResult); return(false); } // Get the current permissions uint CurrentPermissions = (uint)StatModeField.GetValue(StatArgs[1]); // The desired permissions should be executable for every read group uint NewPermissions = CurrentPermissions | ((CurrentPermissions >> 2) & ExecutableBits); // Update them if they don't match if (CurrentPermissions != NewPermissions) { int ChmodResult = (int)ChmodMethod.Invoke(null, new object[] { FileName, NewPermissions }); if (ChmodResult != 0) { Log.WriteError("Chmod() call for {0} failed with error {1}", File.Name, ChmodResult); return(false); } } } } return(true); }