summaryrefslogtreecommitdiff
path: root/raveos-gnome-theme/theme-data/extensions/installed/customreboot@nova1545/grub.js
blob: 6d67ff08556dde715b11c1e75d145a360573987f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
import Gio from "gi://Gio";
import { ExecCommand, Log, LogWarning } from './utils.js';

/**
 * Represents grub
 */
export class Grub {
  /**
   * Get's all available boot options
   * @returns {[Map, string]} Map(title, id), defaultOption
   */
  static async GetBootOptions() {
    try {
      let cfgpath = await this.GetConfig();
      if (cfgpath == "") {
          throw new String("Failed to find grub config");
      }

      let bootOptions = new Map();

      let defualtEn = "";

      let file = Gio.file_new_for_path(cfgpath);
      let [suc, content] = file.load_contents(null);
      if (!suc) {
          throw new String("Failed to load grub config");
      }

      let lines;
      if (content instanceof Uint8Array) {
          lines = new TextDecoder().decode(content);
      }
      else {
          lines = content.toString();
      }

      let entryRx = /^menuentry ['"]([^'"]+)/;
      let defaultRx = /(?<=set default=\")([A-Za-z- ()/0-9]*)(?=\")/
      lines.split('\n').forEach(l => {
          let res = entryRx.exec(l);
          if (res && res.length) {
              bootOptions.set(res[1], res[1]);
          }
          let def = defaultRx.exec(l);
          if (def && def.length) {
              defualtEn = def[0];
          }
      });

      bootOptions.forEach((v, k) => {
          Log(`${k} = ${v}`);
      });

      if (defualtEn == "") defualtEn = bootOptions.keys().next().value;

      return [bootOptions, defualtEn];
          
    } catch (e) {
      LogWarning(e);
      return undefined;
    }
  }

  /**
   * Set's the next boot option
   * @param {string} id 
   * @returns True if the boot option was set, otherwise false
   */
  static async SetBootOption(id) {
    try {
      let [status, stdout, stderr] = await ExecCommand(
          ['/usr/bin/pkexec', '/usr/sbin/grub-reboot', id],
      );
      Log(`Set boot option to ${id}: ${status}\n${stdout}\n${stderr}`);
      return true;
    } catch (e) {
      LogWarning(e);
      return false;
    }
  }

  /**
   * Can we use this bootloader?
   * @returns True if useable otherwise false
   */
  static async IsUseable() {
    return await this.GetConfig() !== "";
  }

  /**
   * Get's grub config file
   * @returns A string containing the location of the config file, if none is found returns a blank string
   */
  static async GetConfig() {
    let paths = ["/boot/grub/grub.cfg", "/boot/grub2/grub.cfg"];

    let file;

    for (let i = 0; i < paths.length; i++) {
        file = Gio.file_new_for_path(paths[i]);
        if (file.query_exists(null)) {
            return paths[i];
        }
    }

    return "";
  }

  /**
   * Copies a custom grub script to allow the extension to quickly reboot into another OS
   * If anyone reads this: Idk how to combine these into one pkexec call, if you do please leave a commit fixing it
   */
  static async EnableQuickReboot(ext) {
    try {
      let [status, stdout, stderr] = await ExecCommand([
          'pkexec',
          'sh',
          '-c',
          `/usr/bin/cp ${ext.lookupByUUID('customreboot@nova1545').path()}/42_custom_reboot /etc/grub.d/42_custom_reboot && /usr/bin/chmod 755 /etc/grub.d/42_custom_reboot && /usr/sbin/update-grub`
        ]);

      if (status !== 0) {
          return false;
      }

      return true;
    }
    catch (e) {
        LogWarning(e);
        return false;
    }
  }
  

  /**
   * Removes the script used to allow the extension to quickly reboot into another OS without waiting for grub's timeout
   * If anyone reads this: Idk how to combine these into one pkexec call, if you do please leave a commit fixing it
   */
  static async DisableQuickReboot() {
    try {

      let [status, stdout, stderr] = await ExecCommand([
          'pkexec',
          'sh',
          '-c',
          '/usr/bin/rm /etc/grub.d/42_custom_reboot && /usr/sbin/update-grub'
        ]);

      if (status !== 0) {
          return false;
      }

      return true;
    }
    catch (e) {
        LogWarning(e);
        return false;
    }
  }


  /**
   * This boot loader can be quick rebooted
   */
  static async CanQuickReboot() {
    return true;
  }

  /**
   * Checks if /etc/grub.d/42_custom_reboot exists
   */ 
  static async QuickRebootEnabled() {
    try {
      let [status, stdout, stderr] = await ExecCommand(['/usr/bin/cat', '/etc/grub.d/42_custom_reboot'],);
      if (status !== 0) {
          LogWarning(`/etc/grub.d/42_custom_reboot not found`);
          return false;
      }
      Log(`/etc/grub.d/42_custom_reboot found`);

      return true;
    }
    catch (e) {
        LogWarning(e);
        return false;
    }
  }

  static async SetReadable() {
    try {
      const config = GetConfig();
      let [status, stdout, stderr] = await ExecCommand(['/usr/bin/pkexec', '/usr/bin/chmod', '644', config],);
      if (status !== 0) {
          Log(`Failed to make ${config} readable`);
          return false;
      }
      Log(`Made ${config} readable`);
      return true;
    }
    catch (e) {
        Log(e);
        return false;
    }
  }
}