~teejee2008/ukuu/trunk

1 by Tony George
Initial commit
1
using TeeJee.Logging;
2
using TeeJee.FileSystem;
48 by Tony George
Updated Utility libraries
3
using TeeJee.JsonHelper;
4
using TeeJee.ProcessHelper;
1 by Tony George
Initial commit
5
using TeeJee.System;
6
using TeeJee.Misc;
7
8
public class LinuxKernel : GLib.Object, Gee.Comparable<LinuxKernel> {
9
	public string name = "";
10
	public string version = "";
11
	public string version_main = "";
12
	public string version_extra = "";
13
	public string version_package = "";
14
	public string type = "";
15
	public string page_uri = "";
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
16
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
17
	public int version_maj = -1;
18
	public int version_min = -1;
19
	public int version_point = -1;
1 by Tony George
Initial commit
20
	
21
	public Gee.HashMap<string,string> deb_list = new Gee.HashMap<string,string>();
12 by Tony George
Added option to uninstall official Ubuntu kernels
22
	public Gee.HashMap<string,string> apt_pkg_list = new Gee.HashMap<string,string>();
1 by Tony George
Initial commit
23
12 by Tony George
Added option to uninstall official Ubuntu kernels
24
	public static Gee.HashMap<string,Package> pkg_list_installed;
25
	
1 by Tony George
Initial commit
26
	public bool is_installed = false;
27
	public bool is_running = false;
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
28
	public bool is_mainline = false;
29
	public bool is_mainline_package = false; // TODO: remove this
30
	
1 by Tony George
Initial commit
31
	public string deb_header = "";
32
	public string deb_header_all = "";
33
	public string deb_image = "";
34
	public string deb_image_extra = "";
35
	
36
	// static
37
	
62 by Tony George
Added option to display GRUB menu at boot time
38
	public static string URI_KERNEL_UBUNTU_MAINLINE = "http://kernel.ubuntu.com/~kernel-ppa/mainline/";
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
39
	public static string CACHE_DIR = "/var/cache/ukuu";
62 by Tony George
Added option to display GRUB menu at boot time
40
	public static string NATIVE_ARCH;
41
	public static string LINUX_DISTRO;
42
	public static string RUNNING_KERNEL;
43
	public static string CURRENT_USER;
44
	public static string CURRENT_USER_HOME;
67 by Tony George
Added option to set the timeout interval for GRUB menu
45
	public static bool hide_older;
46
	public static bool hide_unstable;
62 by Tony George
Added option to display GRUB menu at boot time
47
	public static bool show_grub_menu;
67 by Tony George
Added option to set the timeout interval for GRUB menu
48
	public static int grub_timeout;
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
49
62 by Tony George
Added option to display GRUB menu at boot time
50
	public static LinuxKernel kernel_active;
51
	public static LinuxKernel kernel_update_major;
52
	public static LinuxKernel kernel_update_minor;
53
	public static LinuxKernel kernel_latest_stable;
1 by Tony George
Initial commit
54
	
12 by Tony George
Added option to uninstall official Ubuntu kernels
55
	public static Gee.ArrayList<LinuxKernel> kernel_list = new Gee.ArrayList<LinuxKernel>();
1 by Tony George
Initial commit
56
57
	public static Regex rex_header = null;
58
	public static Regex rex_header_all = null;
59
	public static Regex rex_image = null;
60
	public static Regex rex_image_extra = null;
61
		
62
	// global progress  ------------
62 by Tony George
Added option to display GRUB menu at boot time
63
	public static string status_line;
64
	public static int64 progress_total;
65
	public static int64 progress_count;
66
	public static bool cancelled;
67
	public static bool task_is_running;
68
	public static bool _temp_refresh;
1 by Tony George
Initial commit
69
70
	// class initialize
71
	
72
	public static void initialize(){
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
73
		new LinuxKernel("", false); // instance must be created before setting static members
1 by Tony George
Initial commit
74
75
		LINUX_DISTRO = check_distribution();
76
		NATIVE_ARCH = check_package_architecture();
77
		RUNNING_KERNEL = check_running_kernel();
78
		initialize_regex();
79
	}
80
81
	// dep: lsb_release
82
	public static string check_distribution(){
83
		string dist = "";
84
		
85
		string std_out, std_err;
86
		int status = exec_sync("lsb_release -sd", out std_out, out std_err);
87
		if ((status == 0) && (std_out != null)){
88
			dist = std_out.strip();
89
			log_msg(_("Distribution") + ": %s".printf(dist));
90
		}
91
		
92
		return dist;
93
	}
94
95
	// dep: dpkg
96
	public static string check_package_architecture(){
97
		string arch = "";
98
		
99
		string std_out, std_err;
100
		int status = exec_sync("dpkg --print-architecture", out std_out, out std_err);
101
		if ((status == 0) && (std_out != null)){
102
			arch = std_out.strip();
103
			log_msg(_("System architecture") + ": %s".printf(arch));
104
		}
105
106
		return arch;
107
	}
108
109
	// dep: uname
110
	public static string check_running_kernel(){
111
		string ver = "";
112
		
113
		string std_out;
114
		exec_sync("uname -r", out std_out, null);
23 by Tony George
Fixed parsing of ubuntu kernel version number
115
		log_debug(std_out);
116
		
1 by Tony George
Initial commit
117
		ver = std_out.strip().replace("\n","");
118
		log_msg("Running kernel" + ": %s".printf(ver));
23 by Tony George
Fixed parsing of ubuntu kernel version number
119
120
		exec_sync("uname -a", out std_out, null);
121
		log_debug(std_out);
122
123
		string[] arr = std_out.split(ver);
124
		if (arr.length > 0){
34 by Tony George
Fixed parsing of version string in format like '#40~14.04.1'
125
			string[] parts = arr[1].strip().split_set(" -_~");
23 by Tony George
Fixed parsing of ubuntu kernel version number
126
			string partnum = parts[0].strip();
127
			if (partnum.has_prefix("#")){
128
				partnum = partnum[1:partnum.length];
129
				if (is_numeric(partnum) && (partnum.length <= 3)){
130
					var kern = new LinuxKernel.from_version(ver);
131
					ver = "%s.%s".printf(kern.version_main, partnum);
132
				}
133
			}
134
		}
135
136
		log_msg("Kernel version" + ": %s".printf(ver));
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
137
		
1 by Tony George
Initial commit
138
		return ver;
139
	}
140
141
	public static void initialize_regex(){
142
		try{
143
			//linux-headers-3.4.75-030475-generic_3.4.75-030475.201312201255_amd64.deb
144
			rex_header = new Regex("""linux-headers-[a-zA-Z0-9.\-_]*generic_[a-zA-Z0-9.\-]*_""" + NATIVE_ARCH + ".deb");
145
146
			//linux-headers-3.4.75-030475_3.4.75-030475.201312201255_all.deb
147
			rex_header_all = new Regex("""linux-headers-[a-zA-Z0-9.\-_]*_all.deb""");
148
149
			//linux-image-3.4.75-030475-generic_3.4.75-030475.201312201255_amd64.deb
150
			rex_image = new Regex("""linux-image-[a-zA-Z0-9.\-_]*generic_([a-zA-Z0-9.\-]*)_""" + NATIVE_ARCH + ".deb");
151
152
			//linux-image-extra-3.4.75-030475-generic_3.4.75-030475.201312201255_amd64.deb
153
			rex_image_extra = new Regex("""linux-image-extra-[a-zA-Z0-9.\-_]*generic_[a-zA-Z0-9.\-]*_""" + NATIVE_ARCH + ".deb");
154
		}
155
		catch (Error e) {
156
			log_error (e.message);
157
		}
158
	}
159
160
	public static bool check_if_initialized(){
161
		bool ok = (NATIVE_ARCH.length > 0);
162
		if (!ok){
163
			log_error("LinuxKernel: Class should be initialized before use!");
164
			exit(1);
165
		}
166
		return ok;
167
	}
168
8 by Tony George
Fixed: Index files will be downloaded one-by-one to avoid issues on some systems; Added option to clean cache 'sudo ukuu --clean-cache; Main index file will be refreshed on every run;
169
	public static void clean_cache(){
170
		if (dir_exists(CACHE_DIR)){
171
			bool ok = dir_delete(CACHE_DIR);
172
			if (ok){
173
				log_msg("Removed cached files in '%s'".printf(CACHE_DIR));
174
			}
175
		}
176
	}
177
	
1 by Tony George
Initial commit
178
	// contructor
179
	
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
180
	public LinuxKernel(string _name, bool _is_mainline){
1 by Tony George
Initial commit
181
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
182
		if (_name.has_suffix("/")){
183
			this.name = _name[0: _name.length - 1];
1 by Tony George
Initial commit
184
		}
185
		else{
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
186
			this.name = _name;
1 by Tony George
Initial commit
187
		}
188
189
		// parse version string ---------
190
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
191
		version = this.name;
1 by Tony George
Initial commit
192
193
		// remove "v"
194
		if (version.has_prefix("v")){
195
			version = version[1:version.length];
196
		}
197
		
198
		split_version_string(version, out version_main, out version_extra);
199
200
		// set page URI -----------
201
		
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
202
		page_uri = "%s%s".printf(URI_KERNEL_UBUNTU_MAINLINE, _name);
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
203
204
		is_mainline = _is_mainline;
1 by Tony George
Initial commit
205
	}
206
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
207
	public LinuxKernel.from_version(string _version){
208
209
		version = _version;
210
		
1 by Tony George
Initial commit
211
		name = "v" + version;
212
213
		split_version_string(version, out version_main, out version_extra);
214
215
		page_uri = "";
216
	}
217
	
218
	// static
219
	
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
220
	public static void query(bool wait){
1 by Tony George
Initial commit
221
222
		check_if_initialized();
42 by Tony George
Synchronize threads when download counter value is changed
223
		
1 by Tony George
Initial commit
224
		try {
225
			task_is_running = true;
226
			cancelled = false;
227
			Thread.create<void> (query_thread, true);
228
		} catch (ThreadError e) {
229
			task_is_running = false;
230
			log_error (e.message);
231
		}
232
		
233
		if (wait){
234
			while (task_is_running){
235
				sleep(500); //wait
236
			}
237
		}
238
	}
239
240
	private static void query_thread() {
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
241
67 by Tony George
Added option to set the timeout interval for GRUB menu
242
		log_debug("query: hide_older: %s".printf(hide_older.to_string()));
243
		log_debug("query: hide_unstable: %s".printf(hide_unstable.to_string()));
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
244
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
245
		//DownloadManager.reset_counter();
42 by Tony George
Synchronize threads when download counter value is changed
246
		
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
247
		bool refresh = false;
248
		var one_hour_before = (new DateTime.now_local()).add_hours(-1);
249
		if (last_refreshed_date.compare(one_hour_before) < 0){
250
			refresh = true;
251
			log_debug(_("Index is stale"));
252
		}
253
		else{
254
			log_debug(_("Index is fresh"));
255
		}
256
257
		if (refresh){
1 by Tony George
Initial commit
258
			download_index();
259
		}
260
261
		load_index();
262
42 by Tony George
Synchronize threads when download counter value is changed
263
		// TODO: Implement locking for multiple download threads
264
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
265
		var kern_4 = new LinuxKernel.from_version("4.0");
266
		
1 by Tony George
Initial commit
267
		status_line = "";
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
268
		progress_total = 0;
1 by Tony George
Initial commit
269
		progress_count = 0;
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
270
		foreach(var kern in kernel_list){
67 by Tony George
Added option to set the timeout interval for GRUB menu
271
			if (hide_older && (kern.compare_to(kern_4) < 0)){
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
272
				continue;
273
			}
274
67 by Tony George
Added option to set the timeout interval for GRUB menu
275
			if (hide_unstable && kern.is_unstable){
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
276
				continue;
277
			}
278
			
279
			if (kern.is_valid && !kern.cached_page_exists){
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
280
				progress_total += 2;
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
281
			}
282
		}
283
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
284
285
		var downloads = new Gee.ArrayList<DownloadItem>();
286
		var kernels_to_update = new Gee.ArrayList<LinuxKernel>();
287
		
1 by Tony George
Initial commit
288
		foreach(var kern in kernel_list){
289
			if (cancelled){
290
				break;
291
			}
292
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
293
			if (kern.cached_page_exists){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
294
				//log_debug("cached page exists: %s".printf(kern.version_main));
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
295
				kern.load_cached_page();
296
				continue;
297
			}
298
299
			if (!kern.is_valid){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
300
				//log_debug("invalid: %s".printf(kern.version_main));
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
301
				continue;
302
			}
303
67 by Tony George
Added option to set the timeout interval for GRUB menu
304
			if (hide_older && (kern.compare_to(kern_4) < 0)){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
305
				//log_debug("older than 4.0: %s".printf(kern.version_main));
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
306
				continue;
307
			}
308
67 by Tony George
Added option to set the timeout interval for GRUB menu
309
			if (hide_unstable && kern.is_unstable){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
310
				//log_debug("not stable: %s".printf(kern.version_main));
1 by Tony George
Initial commit
311
				continue;
312
			}
313
		
314
			if (!kern.cached_page_exists){
51 by Tony George
Fixed warnings in class AsyncTask
315
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
316
				var item = new DownloadItem(
317
					kern.cached_page_uri,
318
					file_parent(kern.cached_page),
319
					file_basename(kern.cached_page));
320
					
321
				downloads.add(item);
322
				
323
				item = new DownloadItem(
324
					kern.changes_file_uri,
325
					file_parent(kern.changes_file),
326
					file_basename(kern.changes_file));
327
					
328
				downloads.add(item);
329
330
				kernels_to_update.add(kern);
1 by Tony George
Initial commit
331
			}
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
332
		}
333
52 by Tony George
Continue partial downloads
334
		if (downloads.size > 0){
335
			
336
			var mgr = new DownloadTask();
68 by Tony George
Verify downloads after completion; Improved the parsing for aria2;
337
338
			foreach(var item in downloads){
339
				mgr.add_to_queue(item);
340
			}
341
52 by Tony George
Continue partial downloads
342
			mgr.status_in_kb = true;
343
			mgr.prg_count_total = progress_total;
344
			mgr.execute();
345
346
			while (mgr.is_running()){
347
				progress_count = mgr.prg_count;
348
				sleep(300);
349
			}
350
351
			foreach(var kern in kernels_to_update){
352
				kern.load_cached_page();
353
			}
354
		}
355
		
1 by Tony George
Initial commit
356
		check_installed();
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
357
358
		check_updates();
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
359
360
		//check_available();
8 by Tony George
Fixed: Index files will be downloaded one-by-one to avoid issues on some systems; Added option to clean cache 'sudo ukuu --clean-cache; Main index file will be refreshed on every run;
361
		
1 by Tony George
Initial commit
362
		task_is_running = false;
363
	}
364
	
3 by Tony George
v16.4.0
365
	private static bool download_index(){
1 by Tony George
Initial commit
366
367
		check_if_initialized();
368
		
369
		// fetch index.html --------------------------------------
370
371
		dir_create(file_parent(index_page));
372
		
373
		if (file_exists(index_page)){
374
			file_delete(index_page);
375
		}
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
376
377
		var item = new DownloadItem(URI_KERNEL_UBUNTU_MAINLINE, CACHE_DIR, "index.html");
378
		var mgr = new DownloadTask();
68 by Tony George
Verify downloads after completion; Improved the parsing for aria2;
379
		mgr.add_to_queue(item);
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
380
		mgr.status_in_kb = true;
381
		mgr.execute();
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
382
			
7 by Tony George
v16.4.2
383
		var msg = _("Fetching index from kernel.ubuntu.com...");
1 by Tony George
Initial commit
384
		log_msg(msg);
385
		status_line = msg.strip();
386
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
387
		while (mgr.is_running()){
1 by Tony George
Initial commit
388
			sleep(500);
389
		}
390
391
		//log_debug(index_page);
392
		
393
		if (file_exists(index_page)){
394
			log_msg("OK");
395
			return true;
396
		}
397
		else{
398
			log_error("ERR");
399
			return false;
400
		}
401
	}
402
3 by Tony George
v16.4.0
403
	private static void load_index(){
1 by Tony George
Initial commit
404
405
		var list = new Gee.ArrayList<LinuxKernel>();
406
407
		if (!file_exists(index_page)){
408
			return;
409
		}
410
411
		string txt = file_read(index_page);
412
		
413
		// parse index.html --------------------------
414
415
		try{
416
			//<a href="v3.0.16-oneiric/">v3.0.16-oneiric/</a>
417
			var rex = new Regex("""<a href="([a-zA-Z0-9\-._\/]+)">([a-zA-Z0-9\-._]+)[\/]*<\/a>""");
418
419
			MatchInfo match;
420
421
			foreach(string line in txt.split("\n")){
422
				if (rex.match(line, 0, out match)){
423
					if (!match.fetch(2).has_prefix("v")){
424
						continue;
425
					}
426
					
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
427
					var kern = new LinuxKernel(match.fetch(1), true);
1 by Tony George
Initial commit
428
					list.add(kern);
429
				}
430
			}
431
432
			list.sort((a,b)=>{
433
				return a.compare_to(b) * -1;
434
			});
435
		}
436
		catch (Error e) {
437
			log_error (e.message);
438
		}
439
440
		kernel_list = list;
441
	}
442
443
	public static void check_installed(){
444
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
445
		log_debug("check_installed");
446
		
1 by Tony George
Initial commit
447
		foreach(var kern in kernel_list){
448
			kern.is_installed = false;
449
			kern.is_running = false;
450
		}
451
12 by Tony George
Added option to uninstall official Ubuntu kernels
452
		pkg_list_installed = Package.query_installed_packages();
1 by Tony George
Initial commit
453
454
		var pkg_versions = new Gee.ArrayList<string>();
455
		
12 by Tony George
Added option to uninstall official Ubuntu kernels
456
		foreach(var pkg in pkg_list_installed.values){
1 by Tony George
Initial commit
457
			if (pkg.name.contains("linux-image")){
458
				if (!pkg_versions.contains(pkg.version_installed)){
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
459
					
1 by Tony George
Initial commit
460
					pkg_versions.add(pkg.version_installed);
461
					log_msg("Found installed" + ": %s".printf(pkg.version_installed));
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
462
463
					string kern_name = "v%s".printf(pkg.version_installed);
464
					var kern = new LinuxKernel(kern_name, false);
465
					kern.is_installed = true;
12 by Tony George
Added option to uninstall official Ubuntu kernels
466
					kern.set_apt_pkg_list();
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
467
					
468
					if (kern.is_mainline_package){
469
						continue;
470
					}
471
					
472
					bool found = false;
473
					foreach(var kernel in kernel_list){
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
474
						if (kernel.version_main == kern.version_main){
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
475
							found = true;
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
476
							kernel.apt_pkg_list = kern.apt_pkg_list;
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
477
							break;
478
						}
479
					}
480
					
481
					if (!found){
482
						kernel_list.add(kern);
483
					}
1 by Tony George
Initial commit
484
				}
485
			}
486
		}
487
488
		foreach (string pkg_version in pkg_versions){
489
			foreach(var kern in kernel_list){
490
				if (kern.version_package == pkg_version){
491
					kern.is_installed = true;
492
				}
493
			}
494
		}
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
495
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
496
		// Find and tag the running kernel in list ------------------
497
		
498
		// Running: 4.2.7-040207-generic
499
		// Package: 4.2.7-040207.201512091533
500
501
		// Running: 4.4.0-28-generic
502
		// Package: 4.4.0-28.47
503
		
504
		string ver_running = RUNNING_KERNEL.replace("-generic","");
23 by Tony George
Fixed parsing of ubuntu kernel version number
505
		var kern_running = new LinuxKernel.from_version(ver_running);
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
506
		kernel_active = null;
507
		
508
		foreach(var kern in kernel_list){
509
			if (!kern.is_valid){
510
				continue;
511
			}
512
513
			// check mainline kernels only
514
			if (!kern.is_mainline){
515
				continue;
516
			}
517
518
			// compare version_package strings for mainline kernels
519
			if (kern.version_package.length > 0) {
520
				string ver_pkg_short = kern.version_package[0 : kern.version_package.last_index_of(".")];
521
522
				if (ver_pkg_short == ver_running){
523
					kern.is_running = true;
524
					kern.is_installed = true;
525
					kernel_active = kern;
526
					break;
527
				}
528
			}
529
		}
530
531
		if (kernel_active == null){
532
			foreach(var kern in kernel_list){
533
				if (!kern.is_valid){
534
					continue;
535
				}
536
537
				// check ubuntu kernels only
538
				if (kern.is_mainline){
539
					continue;
540
				}
541
23 by Tony George
Fixed parsing of ubuntu kernel version number
542
				if (kern_running.version_main == kern.version_main){
543
					kern.is_running = true;
544
					kern.is_installed = true;
545
					kernel_active = kern;
546
					break;
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
547
				}
548
			}
549
		}
550
		
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
551
		kernel_list.sort((a,b)=>{
552
			return a.compare_to(b) * -1;
553
		});
1 by Tony George
Initial commit
554
	}
555
12 by Tony George
Added option to uninstall official Ubuntu kernels
556
	public static void check_available(){
557
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
558
		log_debug("check_available");
559
		
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
560
		var list = Package.query_available_packages("^linux-image");
12 by Tony George
Added option to uninstall official Ubuntu kernels
561
562
		var pkg_versions = new Gee.ArrayList<string>();
563
		
564
		foreach(var pkg in list.values){
565
			if (pkg.name.contains("linux-image")){
566
				if (!pkg_versions.contains(pkg.version_installed)){
567
					
568
					pkg_versions.add(pkg.version_installed);
569
					log_msg("Found upgrade" + ": %s".printf(pkg.version_installed));
570
571
					string kern_name = "v%s".printf(pkg.version_installed);
572
					var kern = new LinuxKernel(kern_name, false);
573
					kern.is_installed = false;
574
575
					if (kern.is_mainline_package){
576
						continue;
577
					}
578
					
579
					bool found = false;
580
					foreach(var kernel in kernel_list){
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
581
						if (kernel.version_main == kern.version_main){
12 by Tony George
Added option to uninstall official Ubuntu kernels
582
							found = true;
583
							break;
584
						}
585
					}
586
					
587
					if (!found){
588
						kernel_list.add(kern);
589
					}
590
				}
591
			}
592
		}
593
594
		kernel_list.sort((a,b)=>{
595
			return a.compare_to(b) * -1;
596
		});
597
	}
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
598
599
	public static void check_updates(){
600
601
		log_debug("check_updates");
602
		
603
		kernel_update_major = null;
604
		kernel_update_minor = null;
605
		kernel_latest_stable = null;
606
		
607
		var kern_running = new LinuxKernel.from_version(LinuxKernel.RUNNING_KERNEL);
608
		foreach(var kern in LinuxKernel.kernel_list){
609
			// skip invalid
610
			if (!kern.is_valid){
611
				continue;
612
			}
35 by Tony George
Update notification will not be shown if the new kernel is already installed on the system but not currently active
613
			
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
614
			// skip unstable
615
			if (kern.is_unstable){
616
				continue;
617
			}
618
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
619
			if (kernel_latest_stable == null){
620
				kernel_latest_stable = kern;
621
				log_debug("latest stable kernel -> %s".printf(kern.version_main));
622
			}
623
			
35 by Tony George
Update notification will not be shown if the new kernel is already installed on the system but not currently active
624
			// skip installed
625
			if (kern.is_installed){
626
				continue;
627
			}
628
36 by Tony George
Fixed an error with update notifications
629
			//log_msg("check: %s".printf(kern.version_main));
630
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
631
			bool major_available = false;
632
			bool minor_available = false;
633
			
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
634
			if (kern.version_maj > kern_running.version_maj){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
635
				major_available = true;
636
			}
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
637
			else if (kern.version_maj == kern_running.version_maj){
638
				if (kern.version_min > kern_running.version_min){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
639
					major_available = true;
640
				}
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
641
				else if (kern.version_min == kern_running.version_min){
642
					if (kern.version_point > kern_running.version_point){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
643
						minor_available = true;
644
					}
645
				}
646
			}
647
			
648
			if (major_available && (kernel_update_major == null)){
649
				kernel_update_major = kern;
36 by Tony George
Fixed an error with update notifications
650
				log_debug("major update -> %s".printf(kern.version_main));
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
651
			}
652
			
653
			if (minor_available && (kernel_update_minor == null)){
654
				kernel_update_minor = kern;
36 by Tony George
Fixed an error with update notifications
655
				log_debug("minor update -> %s".printf(kern.version_main));
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
656
			}
657
658
			if ((kernel_update_major != null)
659
				&& (kernel_update_minor != null)
660
				&& (kernel_latest_stable != null)){
661
					
662
				break;
663
			}
664
		}
665
	}
666
69 by Tony George
Console: Added support to download or remove multiple kernels
667
	
1 by Tony George
Initial commit
668
	// helpers
669
	
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
670
	public void split_version_string(
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
671
		string version_string,
672
		out string ver_main,
673
		out string ver_extra){
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
674
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
675
		string[] arr = version_string.split_set (".-_");
1 by Tony George
Initial commit
676
677
		if (arr.length == 0){
678
			ver_main = "";
679
			ver_extra = "";
680
			return;
681
		}
682
		
683
		int i = 0;
684
685
		// take first part
686
		ver_main = arr[i++];
687
688
		// remove "v"
689
		if (ver_main.has_prefix("v")){
690
			ver_main = ver_main[1:ver_main.length];
691
		}
692
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
693
		version_maj = int.parse(ver_main);
694
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
695
		// append all numbers which are 3 digits or less
696
		while (i < arr.length){
697
			if (is_numeric(arr[i]) && (arr[i].length <= 3)){
53 by Tony George
Fixed a bug in update check - user would sometimes be prompted to install an older version
698
				ver_main += ".%s".printf(arr[i]);
699
				if (version_min == -1){
700
					version_min = int.parse(arr[i]);
701
				}
702
				else if (version_point == -1){
703
					version_point = int.parse(arr[i]);
704
				}
705
				i++;
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
706
			}
707
			else{
708
				break;
709
			}
710
		}
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
711
712
		if (version_point == -1){
713
			ver_main += ".0";
714
			version_point = 0;
715
		}
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
716
		
717
		// v3.11-rc1-saucy
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
718
		if (i < arr.length){
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
719
			// append rc number
1 by Tony George
Initial commit
720
			if (arr[i].contains("rc")){
721
				ver_main += "-%s".printf(arr[i++]);
722
			}
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
723
		}
724
725
		// v3.16.7-ckt26-trusty
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
726
		// v3.16.7-040603ckt26-trusty
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
727
		if (i < arr.length){
728
			if (arr[i].contains("ckt")){
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
729
				ver_main += ".%s".printf(arr[i++].split("ckt")[1]);
730
				is_mainline_package = false;
731
				// -ckt kernels are maintained by the Canonical Kernel Team (CKT)
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
732
			}
733
		}
734
		
735
		// 4.6.3-040603.201606241434
736
		// this version string is the package version of a mainline kernel
737
		
738
		if ((i < arr.length) && ((i+1) < arr.length)){
739
			if (is_numeric(arr[i]) && (arr[i].length == 6)
740
				&& is_numeric(arr[i+1]) && (arr[i+1].length == 12)){
741
					
742
				ver_main += ".%s".printf(arr[i++]);
743
				ver_main += ".%s".printf(arr[i++]);
744
				is_mainline_package = true;
1 by Tony George
Initial commit
745
			}
746
		}
747
748
		// get remaining part
749
		ver_extra = "";
11 by Tony George
Ubuntu's offical kernels will also be displayed in list
750
		if (i < arr.length){
751
			for(; i < arr.length; i++){
752
				ver_extra += "-%s".printf(arr[i]);
753
			}
1 by Tony George
Initial commit
754
		}
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
755
54 by Tony George
Stop the ukuu-notify script after updating it
756
		//log_debug("split: %s, version_main: %s, maj/min/point: %d,%d,%d".printf(version_string, ver_main, version_maj, version_min, version_point));
1 by Tony George
Initial commit
757
	}
758
759
	public int compare_to(LinuxKernel b){
760
		LinuxKernel a = this;
761
		string[] arr_a = a.version_main.split_set (".-_");
762
		string[] arr_b = b.version_main.split_set (".-_");
763
764
		int i = 0;
765
		int x, y;
766
767
		// while both arrays have an element
768
		while ((i < arr_a.length) && (i < arr_b.length)){
769
770
			// continue if equal
771
			if (arr_a[i] == arr_b[i]){
772
				i++;
773
				continue;
774
			}
775
			
776
			// check if number
777
			x = int.parse(arr_a[i]);
778
			y = int.parse(arr_b[i]);
779
			if ((x > 0) && (y > 0)){
780
				// both are numbers
781
				return (x - y);
782
			}
783
			else if ((x == 0) && (y == 0)){
784
				// both are strings
785
				return strcmp(arr_a[i], arr_b[i]);
786
			}
787
			else{
788
				if (x > 0){
789
					return 1;
790
				}
791
				else{
792
					return -1;
793
				}
794
			}
795
		}
796
797
		// one array has less parts than the other and all corresponding parts are equal
798
799
		if (i < arr_a.length){
800
			x = int.parse(arr_a[i]);
801
			if (x > 0){
802
				return 1;
803
			}
804
			else{
805
				return -1;
806
			}
807
		}
808
809
		if (i < arr_b.length){
810
			y = int.parse(arr_b[i]);
811
			if (y > 0){
812
				return -1;
813
			}
814
			else{
815
				return 1;
816
			}
817
		}
818
819
		return (arr_a.length - arr_b.length) * -1; // smaller array is larger version
820
	}
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
821
822
	public void mark_invalid(){
15 by Tony George
Removed notification functionality
823
		string file = "%s/invalid".printf(cache_subdir);
824
		if (!file_exists(file)){
825
			file_write(file, "1");
826
		}
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
827
	}
12 by Tony George
Added option to uninstall official Ubuntu kernels
828
829
	public void set_apt_pkg_list(){
830
		foreach(var pkg in pkg_list_installed.values){
831
			if (!pkg.name.has_prefix("linux-")){
832
				continue;
833
			}
834
			if (pkg.version_installed == version){
835
				apt_pkg_list[pkg.name] = pkg.name;
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
836
				log_debug("Package: %s".printf(pkg.name));
12 by Tony George
Added option to uninstall official Ubuntu kernels
837
			}
838
		}
839
	}
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
840
	
1 by Tony George
Initial commit
841
	// properties
842
843
	public bool is_rc{
844
		get {
845
			return version.contains("-rc");
846
		}
847
	}
848
849
	public bool is_unstable{
850
		get {
851
			return version.contains("-rc") || version.contains("-unstable");
852
		}
853
	}
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
854
855
	public bool is_valid {
856
		get {
857
			return !file_exists("%s/invalid".printf(cache_subdir));
858
		}
859
	}
1 by Tony George
Initial commit
860
	
861
	public static string index_page{
862
		owned get {
863
			return "%s/index.html".printf(CACHE_DIR);
864
		}
865
	}
866
867
	public static DateTime last_refreshed_date{
868
		owned get{
13 by Tony George
Added statusbar in main window; Fixed parsing for active kernel version string;
869
			if (file_get_size(index_page) < 300000){
870
				return (new DateTime.now_local()).add_years(-1);
871
			}
872
			else{
873
				return file_get_modified_date(index_page);
874
			}
1 by Tony George
Initial commit
875
		}
876
	}
877
878
	public string cache_subdir{
879
		owned get {
880
			return "%s/%s".printf(CACHE_DIR, name);
881
		}
882
	}
883
	
884
	public string cached_page{
885
		owned get {
886
			return "%s/index.html".printf(cache_subdir);
887
		}
888
	}
889
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
890
	public string cached_page_uri{
891
		owned get {
892
			return page_uri;
893
		}
894
	}
895
1 by Tony George
Initial commit
896
	public string changes_file{
897
		owned get {
898
			return "%s/CHANGES".printf(cache_subdir);
899
		}
900
	}
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
901
902
	public string changes_file_uri{
903
		owned get {
904
			return "%s%s".printf(page_uri, "CHANGES");
905
		}
906
	}
1 by Tony George
Initial commit
907
	
908
	public bool cached_page_exists{
909
		get {
910
			return file_exists(cached_page);
911
		}
912
	}
913
914
	public string major_version{
915
		owned get {
916
			string[] parts = version_main.split(".");
917
			if (parts.length >= 2){
918
				return "%s.%s".printf(parts[0],parts[1]);
919
			}
920
			return version_main;
921
		}
922
	}
923
924
	public string minor_version{
925
		owned get {
926
			string[] parts = version_main.split(".");
927
			if (parts.length >= 3){
928
				return "%s.%s.%s".printf(parts[0],parts[1],parts[2]);
929
			}
930
			return version_main;
931
		}
932
	}
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
933
934
	public string tooltip_text(){
935
		string txt = "";
936
937
		string list = "";
938
		foreach(string deb in deb_list.keys){
939
			list += "%s\n".printf(deb);
940
		}
941
		if (list.length > 0){
942
			txt += "<b>%s</b>\n\n%s\n".printf(_("Packages Available (DEB)"), list);
943
		}
944
945
		list = "";
946
		foreach(string deb in apt_pkg_list.keys){
947
			list += "%s\n".printf(deb);
948
		}
949
		if (list.length > 0){
950
			txt += "<b>%s</b>\n\n%s\n".printf(_("Packages Installed"), list);
951
		}
952
		
953
		return txt;
954
	}
1 by Tony George
Initial commit
955
	
956
	// load
957
	
3 by Tony George
v16.4.0
958
	private void load_cached_page(){
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
959
			
1 by Tony George
Initial commit
960
		var list = new Gee.HashMap<string,string>();
961
962
		if (!file_exists(cached_page)){
963
			log_error("load_cached_page: " + _("File not found") + ": %s".printf(cached_page));
964
			return;
965
		}
966
967
		string txt = file_read(cached_page);
968
		
969
		// parse index.html --------------------------
970
971
		try{
972
			//<a href="linux-headers-4.6.0-040600rc1-generic_4.6.0-040600rc1.201603261930_amd64.deb">//same deb name//</a>
973
			var rex = new Regex("""<a href="([a-zA-Z0-9\-._]+)">([a-zA-Z0-9\-._]+)<\/a>""");
974
			MatchInfo match;
975
976
			foreach(string line in txt.split("\n")){
977
				if (rex.match(line, 0, out match)){
978
					string file_name = match.fetch(2);
979
					string file_uri = "%s%s".printf(page_uri, match.fetch(1));
980
981
					bool add = false;
982
					
983
					if (rex_header.match(file_name, 0, out match)){
984
						deb_header = file_name;
985
						add = true;
986
					}
987
988
					if (rex_header_all.match(file_name, 0, out match)){
989
						deb_header_all = file_name;
990
						add = true;
991
					}
992
993
					if (rex_image.match(file_name, 0, out match)){
994
						deb_image = file_name;
995
						add = true;
996
						
997
						version_package = match.fetch(1);
998
					}
999
1000
					if (rex_image_extra.match(file_name, 0, out match)){
1001
						deb_image_extra = file_name;
1002
						add = true;
1003
					}
1004
1005
					if (add){
1006
						list[file_name] = file_uri; // add to list
1007
					}
1008
				}
1009
			}
1010
1011
			if ((deb_header.length == 0) || (deb_header_all.length == 0) || (deb_image.length == 0)){
10 by Tony George
Fixed: The progress window would sometimes remain open even after all index files are finished downloading
1012
				mark_invalid();
1 by Tony George
Initial commit
1013
			}
1014
		}
1015
		catch (Error e) {
1016
			log_error (e.message);
1017
		}
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
1018
		
1019
		
1 by Tony George
Initial commit
1020
		deb_list = list;
1021
	}
1022
3 by Tony George
v16.4.0
1023
	private void get_package_version(){
1 by Tony George
Initial commit
1024
1025
		if (NATIVE_ARCH.length == 0){
1026
			log_error("Native architecture is unknown!");
1027
			exit(1);
1028
		}
1029
1030
		//linux_image_pkg_version
1031
		Regex rex_image = null;
1032
		MatchInfo match;
1033
		
1034
		try{
1035
			//linux-image-3.4.75-030475-generic_3.4.75-030475.201312201255_amd64.deb
1036
			rex_image = new Regex("""linux-image-[0-9.\-_]*generic_([0-9.\-]*)_""" + NATIVE_ARCH + ".deb");
1037
		}
1038
		catch (Error e) {
1039
			log_error (e.message);
1040
		}
1041
1042
		foreach(string file_name in deb_list.keys){
1043
			if (rex_image.match(file_name, 0, out match)) {
1044
				
1045
				continue;
1046
			}
1047
		}
1048
	}
1049
	
1050
	// actions
1051
1052
	public static void print_list(){
1053
		log_msg("");
1054
		log_draw_line();
1055
		log_msg(_("Available Kernels"));
1056
		log_draw_line();
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1057
1058
		var kern_4 = new LinuxKernel.from_version("4.0");
1 by Tony George
Initial commit
1059
		foreach(var kern in kernel_list){
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1060
			if (!kern.is_valid){
1061
				continue;
1062
			}
67 by Tony George
Added option to set the timeout interval for GRUB menu
1063
			if (hide_unstable && kern.is_unstable){
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1064
				continue;
1065
			}
67 by Tony George
Added option to set the timeout interval for GRUB menu
1066
			if (hide_older && (kern.compare_to(kern_4) < 0)){
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1067
				continue;
1068
			}
1069
			
1 by Tony George
Initial commit
1070
			var extra = kern.version_extra;
1071
			extra = extra.has_prefix("-") ? extra[1:extra.length] : extra;
1072
			var desc = kern.is_running ? _("Running") : (kern.is_installed ? _("Installed") : "");
1073
			
1074
			log_msg("%-30s %-15s %-15s %s".printf(kern.name, kern.version_main, extra, desc));
1075
		}
1076
	}
1077
69 by Tony George
Console: Added support to download or remove multiple kernels
1078
	public static bool download_kernels(Gee.ArrayList<LinuxKernel> selected_kernels){
1079
		foreach(var kern in selected_kernels){
1080
			kern.download_packages();
1081
		}
1082
		return true;
1083
	}
1084
	
6 by Tony George
Added a more reliable check for internet connectivity
1085
	// dep: aria2c
3 by Tony George
v16.4.0
1086
	public bool download_packages(){
1087
		bool ok = true;
1088
1089
		check_if_initialized();
1090
1091
		foreach(string file_name in deb_list.keys){
1092
			string file_path = "%s/%s/%s".printf(cache_subdir, NATIVE_ARCH, file_name);
1093
52 by Tony George
Continue partial downloads
1094
			if (file_exists(file_path) && !file_exists(file_path + ".aria2c")){
3 by Tony George
v16.4.0
1095
				continue;
1096
			}
1097
1098
			dir_create(file_parent(file_path));
1099
1100
			stdout.printf("\n" + _("Downloading") + ": '%s'... \n".printf(file_name));
1101
			stdout.flush();
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
1102
1103
			var item = new DownloadItem(deb_list[file_name], file_parent(file_path), file_basename(file_path));
68 by Tony George
Verify downloads after completion; Improved the parsing for aria2;
1104
			
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
1105
			var mgr = new DownloadTask();
68 by Tony George
Verify downloads after completion; Improved the parsing for aria2;
1106
			mgr.add_to_queue(item);
3 by Tony George
v16.4.0
1107
			mgr.status_in_kb = true;
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
1108
			mgr.execute();
3 by Tony George
v16.4.0
1109
49 by Tony George
Cache refresh is now extremely fast; Fixed crash while refreshing cache;
1110
			while (mgr.is_running()){
3 by Tony George
v16.4.0
1111
				sleep(200);
1112
38 by Tony George
Fixed: The download progress status line is not refreshed correctly in terminal window
1113
				stdout.printf("\r%-60s".printf(mgr.status_line.replace("\n","")));
3 by Tony George
v16.4.0
1114
				stdout.flush();
1115
			}
1116
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1117
			if (file_exists(file_path)){				
3 by Tony George
v16.4.0
1118
				stdout.printf("\r%-70s\n".printf(_("OK")));
1119
				stdout.flush();
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1120
				
1121
				if (user_is_admin()){
1122
					chown(file_path, CURRENT_USER, CURRENT_USER);
43 by Tony George
Added option to cancel the initial refresh window
1123
					chmod(file_path, "a+rw");
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1124
				}
3 by Tony George
v16.4.0
1125
			}
1126
			else{
1127
				stdout.printf("\r%-70s\n".printf(_("ERROR")));
1128
				stdout.flush();
1129
				ok = false;
1130
			}
1131
		}
1132
		
1133
		return ok;
1134
	}
1135
6 by Tony George
Added a more reliable check for internet connectivity
1136
	// dep: dpkg
1 by Tony George
Initial commit
1137
	public bool install(bool write_to_terminal){
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1138
1139
		// check if installed
1140
		if (is_installed){
1141
			log_error(_("This kernel is already installed."));
1142
			return false;
1143
		}
1144
					
1 by Tony George
Initial commit
1145
		bool ok = download_packages();
1146
		int status = -1;
1147
		
1148
		if (ok){
1149
1150
			log_msg("Preparing to install '%s'".printf(name));
1151
			
1152
			var cmd = "cd '%s/%s' && dpkg -i ".printf(cache_subdir, NATIVE_ARCH);
1153
1154
			foreach(string file_name in deb_list.keys){
1155
				cmd += "'%s' ".printf(file_name);
1156
			}
1157
			
1158
			if (write_to_terminal){
1159
				log_msg("");
1160
				status = Posix.system(cmd); // execute
1161
				log_msg("");
1162
			}
1163
			else{
1164
				status = exec_script_sync(cmd); // execute
1165
			}
1166
1167
			ok = (status == 0);
62 by Tony George
Added option to display GRUB menu at boot time
1168
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
1169
			update_grub_menu();
1170
1 by Tony George
Initial commit
1171
			if (ok){
3 by Tony George
v16.4.0
1172
				log_msg(_("Installation completed. A reboot is required to use the new kernel."));
1 by Tony George
Initial commit
1173
			}
1174
			else{
1175
				log_error(_("Installation completed with errors"));
1176
			}
1177
		}
1178
1179
		return ok;
1180
	}
1181
6 by Tony George
Added a more reliable check for internet connectivity
1182
	// dep: dpkg
69 by Tony George
Console: Added support to download or remove multiple kernels
1183
	public static bool remove_kernels(Gee.ArrayList<LinuxKernel> selected_kernels){
1184
		bool ok = true;
1185
		int status = -1;
1186
1187
		// check if running
1188
1189
		foreach(var kern in selected_kernels){
1190
			if (kern.is_running){
1191
				log_error(_("Selected kernel is currently running and cannot be removed.\n Install another kernel before removing this one."));
1192
				return false;
1193
			}
1194
		}
1195
1196
		log_msg(_("Preparing to remove selected kernels"));
1197
		
1198
		var cmd = "dpkg -r ";
1199
1200
		foreach(var kern in selected_kernels){
1201
			
1202
			if (kern.apt_pkg_list.size > 0){
1203
				foreach(var pkg_name in kern.apt_pkg_list.values){
1204
					if (!pkg_name.has_prefix("linux-tools")
1205
						&& !pkg_name.has_prefix("linux-libc")){
1206
							
1207
						cmd += "'%s' ".printf(pkg_name);
1208
					}
1209
				}
1210
			}
1211
			else if (kern.deb_list.size > 0){
1212
				// get package names from deb file names
1213
				foreach(string file_name in kern.deb_list.keys){
1214
					cmd += "'%s' ".printf(file_name.split("_")[0]);
1215
				}
1216
			}
1217
			else{
1218
				stdout.printf("");
1219
				log_error("Could not find the packages to remove!");
1220
				return false;
1221
			}
1222
		}
1223
1224
		log_msg("");
1225
		status = Posix.system(cmd); // execute
1226
		log_msg("");
1227
1228
		ok = (status == 0);
1229
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
1230
		update_grub_menu();
69 by Tony George
Console: Added support to download or remove multiple kernels
1231
1232
		if (ok){
1233
			log_msg(_("Un-install completed"));
1234
		}
1235
		else{
1236
			log_error(_("Un-install completed with errors"));
1237
		}
1238
1239
		return ok;
1240
	}
1241
1242
	// dep: dpkg
1 by Tony George
Initial commit
1243
	public bool remove(bool write_to_terminal){
1244
		bool ok = true;
1245
		int status = -1;
18 by Tony George
Download index only if older than an hour; Start in non-admin mode and prompt user before installing and removing kernels; Use pkexec for getting admin priviledges;
1246
1247
		// check if running
1248
		if (is_running){
1249
			log_error(_("This kernel is currently running and cannot be removed.\n Install another kernel before removing this one."));
1250
			return false;
1251
		}
1252
					
1 by Tony George
Initial commit
1253
		log_msg("Preparing to remove '%s'".printf(name));
1254
		
1255
		var cmd = "dpkg -r ";
12 by Tony George
Added option to uninstall official Ubuntu kernels
1256
1257
		if (apt_pkg_list.size > 0){
1258
			foreach(var pkg_name in apt_pkg_list.values){
1259
				if (!pkg_name.has_prefix("linux-tools")
1260
					&& !pkg_name.has_prefix("linux-libc")){
1261
						
1262
					cmd += "'%s' ".printf(pkg_name);
1263
				}
1264
			}
1265
		}
1266
		else if (deb_list.size > 0){
1267
			// get package names from deb file names
1268
			foreach(string file_name in deb_list.keys){
1269
				cmd += "'%s' ".printf(file_name.split("_")[0]);
1270
			}
1271
		}
1272
		else{
1273
			stdout.printf("");
1274
			log_error("Could not find the packages to remove!");
1275
			return false;
1 by Tony George
Initial commit
1276
		}
1277
1278
		if (write_to_terminal){
1279
			log_msg("");
1280
			status = Posix.system(cmd); // execute
1281
			log_msg("");
1282
		}
1283
		else{
1284
			status = exec_script_sync(cmd); // execute
1285
		}
1286
		ok = (status == 0);
62 by Tony George
Added option to display GRUB menu at boot time
1287
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
1288
		update_grub_menu();
62 by Tony George
Added option to display GRUB menu at boot time
1289
1 by Tony George
Initial commit
1290
		if (ok){
12 by Tony George
Added option to uninstall official Ubuntu kernels
1291
			log_msg(_("Un-install completed"));
1 by Tony George
Initial commit
1292
		}
1293
		else{
12 by Tony George
Added option to uninstall official Ubuntu kernels
1294
			log_error(_("Un-install completed with errors"));
1 by Tony George
Initial commit
1295
		}
1296
1297
		return ok;
1298
	}
1299
69 by Tony George
Console: Added support to download or remove multiple kernels
1300
	// dep: update-grub
1301
	public static bool update_grub_menu(){
62 by Tony George
Added option to display GRUB menu at boot time
1302
1303
		string grub_file = "/etc/default/grub";
1304
		if (!file_exists(grub_file)){
1305
			return false;
1306
		}
1307
		
1308
		string txt = "";
1309
		bool file_changed = false;
1310
		bool grub_timeout_found = false;
1311
		
1312
		foreach(var line in file_read(grub_file).split("\n")){
1313
			
1314
			if (line.up().contains("GRUB_HIDDEN_TIMEOUT=") && !line.strip().has_prefix("#")){
1315
				// comment the line
1316
				txt += "#%s\n".printf(line);
1317
				file_changed = true;
1318
			}
1319
			else if (line.up().contains("GRUB_TIMEOUT=")){
65 by Tony George
Fixed some build issues
1320
				
62 by Tony George
Added option to display GRUB menu at boot time
1321
				int64 seconds = 0;
1322
				if (int64.try_parse(line.split("=")[1], out seconds)){
1323
					// value can be 0, > 0 or -1 (indefinite wait)
67 by Tony George
Added option to set the timeout interval for GRUB menu
1324
					if (seconds == grub_timeout){
1325
						txt += "%s\n".printf(line);
1326
					}
1327
					else{
1328
						txt += "%s=%d\n".printf("GRUB_TIMEOUT", grub_timeout);
62 by Tony George
Added option to display GRUB menu at boot time
1329
						file_changed = true;
1330
					}
1331
				}
1332
				else{
67 by Tony George
Added option to set the timeout interval for GRUB menu
1333
					txt += "%s=%d\n".printf("GRUB_TIMEOUT", grub_timeout);
62 by Tony George
Added option to display GRUB menu at boot time
1334
					file_changed = true;
1335
				}
1336
				grub_timeout_found = true;
1337
			}
1338
			else if (line.up().contains("GRUB_TIMEOUT_STYLE=") && !line.strip().has_prefix("#")){
1339
				// comment the line; same as setting value to 'menu'
1340
				txt += "#%s\n".printf(line);
1341
				file_changed = true;
1342
			}
1343
			else if (line.up().contains("GRUB_HIDDEN_TIMEOUT_QUIET=") && !line.strip().has_prefix("#")){
1344
				// comment the line; deprecated option
1345
				txt += "#%s\n".printf(line);
1346
				file_changed = true;
1347
			}
1348
			else{
1349
				txt += "%s\n".printf(line);
1350
			}
1351
		}
1352
1353
		if (!grub_timeout_found){
67 by Tony George
Added option to set the timeout interval for GRUB menu
1354
			txt += "%s=%d\n".printf("GRUB_TIMEOUT", grub_timeout);
62 by Tony George
Added option to display GRUB menu at boot time
1355
			file_changed = true;
1356
		}
1357
		
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
1358
		if (file_changed && show_grub_menu){
1359
			file_write(grub_file, txt);
62 by Tony George
Added option to display GRUB menu at boot time
1360
		}
1361
71 by Tony George
Fixed double entries in list for installed -ckt kernels; Added Refresh buttom to main window
1362
		log_msg(_("Updating GRUB menu"));
62 by Tony George
Added option to display GRUB menu at boot time
1363
		
1364
		string cmd = "update-grub";
1365
		Posix.system(cmd);
1366
1367
		return true;
1368
	}
1 by Tony George
Initial commit
1369
}
1370