Beispiel #1
0
        /// <summary>
        /// Writes all values to the config file. If the config file does not
        /// exist, it gets created, along with all the directories involved.
        /// An existing file will get overwritten.
        /// </summary>
        public static void SaveConfig()
        {
            var options = new JsonSerializerOptions
            {
                WriteIndented = true
            };

            if (_model == null)
            {
                _model = new PathConfModel();
            }
            Directory.CreateDirectory(Path.GetDirectoryName(ConfFile));
            string serialized = JsonSerializer.Serialize(_model, _model.GetType(), options);

            File.WriteAllText(ConfFile, serialized);

            // Because in Linux "Root Owns Everything", we need to change the owner of the
            // config back to our current user
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && SystemAndShellUtils.IsAdmin())
            {
                var user = SystemAndShellUtils.GetCurrentUser();
                _shell.Term($"chown {user} {ConfFile}");
                _shell.Term($"chown {user} {Path.GetDirectoryName(ConfFile)}");
            }
        }
        /// <summary>
        /// Tries launching the installer exectuable from %TEMP% using PolicyKit's "pkexec" command.
        /// </summary>
        /// <param name="args">The command line arguments to pass into the installer.</param>
        /// <param name="copyCurrentProcessExecutable">If set to <c>true</c>, the currently running process
        /// exectuable will be copied to the temp directory as the installer executable to run, if it isn't
        /// already running from there.</param>
        /// <returns>Returns <c>true</c> if the installer could be launched using PolicyKit, or <c>false</c> otherwise.</returns>
        public static bool LaunchInstallerUsingPolKit(string args = "", bool copyCurrentProcessExecutable = false)
        {
            Log.Information("Trying to launch installer using PolicyKit");

            // If PolicyKit is not available, there is no point in continuing.
            if (!IsPolKitAvailable())
            {
                Log.Warning("PolicyKit NOT available, bailing out");
                return(false);
            }
            Log.Information("PolicyKit available, pkexec exists!");

            // Check if the policy file for the installer exists, this is needed for the polkit invokation
            if (!File.Exists(Path.Combine("/usr/share/polkit-1/actions",
                                          "org.freedesktop.policykit.SQRLPlatformAwareInstaller_linux.policy")))
            {
                Log.Warning("PolicyKit policy file for installer not found, bailing out");
                return(false);
            }
            Log.Information("Found existing PolicyKit policy file for Installer!");

            string currentExePath = Process.GetCurrentProcess().MainModule.FileName;
            string tempExePath    = $"/tmp/{CommonUtils.GetInstallerByPlatform()}";

            if (copyCurrentProcessExecutable)
            {
                // Copy the current installer to /tmp/ so that it can comply with polkit requirements. Note this
                // doesn't work correctly if you are in debug mode. In debug mode the file you are running is a dll,
                // not an executable, so be mindful of this

                if (currentExePath != tempExePath)
                {
                    Log.Information($"Copying Installer from \"{currentExePath}\" to \"{tempExePath}\"");
                    File.Copy(currentExePath, tempExePath, true);
                    SystemAndShellUtils.Chmod(tempExePath, 777);
                }
            }

            // At this point, the installer exectuable must exist in the temp dir,
            // so if it doesn't, bail out.
            if (!File.Exists(tempExePath))
            {
                Log.Error($"Installer binary not found in \"{tempExePath}\", bailing out");
                return(false);
            }

            // PolKit invocation forbids having a "dead" parent, so if we invoke PolKit directly from here
            // and then kill the process, it will abort. First we need to write the polkit invocation
            // to a shell script which is invoked externally, so that we can kill our current instance of
            // the installer cleanly.

            Log.Information($"Creating PolicyKit launcher script");
            var tmpScript = Path.GetTempFileName().Replace(".tmp", ".sh");

            using (StreamWriter sw = new StreamWriter(tmpScript))
            {
                sw.WriteLine("#!/bin/sh");
                sw.WriteLine(string.IsNullOrWhiteSpace(args) ?
                             $"{SystemAndShellUtils.GetPolKitLocation()} {tempExePath}" :
                             $"{SystemAndShellUtils.GetPolKitLocation()} {tempExePath} {args}");
            }
            Log.Information($"Created PolicyKit launcher script at: {tmpScript}");
            SetExecutableBit(tmpScript);

            Log.Information($"Launching installer with args: {args}");
            Process proc = new Process();

            proc.StartInfo.FileName         = tmpScript;
            proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(tmpScript);
            proc.Start();
            return(true);
        }