Merge branch 'master' into patch-1

This commit is contained in:
Tony George 2020-11-16 17:57:15 +05:30 committed by GitHub
commit 22cd8d1899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 14388 additions and 16382 deletions

View File

@ -1,17 +0,0 @@
src/timeshift
src/timeshift-gtk
designs/
release/source
release/amd64
release/i386
release/armel
release/armhf
release/*.deb
release/*.run
*.geany
*.mo
*.c
*.o
.git
.bzr
*~

View File

@ -7,7 +7,9 @@ assignees: ''
---
**Note:** This application is provided "as-is" without support or warranty. Due to lack of time, I check this tracker once every few months. If you need help with an issue, consider posting the issue on Linux Mint forums where there are more people to help you out.
**Note:** This application is provided "as-is" without support or warranty. The purpose of this tracker is to keep track of issues. It is checked once a year when the app is being updated. If you face any issue you can report it here but please keep in mind that there is no dedicated support. The issue will be investigated and fixed during the next update which may occur many months after you report the issue.
**Note:** If you are a Linux Mint user and you need help with an issue, consider posting the issue on [Linux Mint forums](https://forums.linuxmint.com) where there are more people to help you out.
**Describe the bug**
A clear and concise description of what the bug is.

View File

@ -7,7 +7,7 @@ assignees: ''
---
**Note:** This application is provided "as-is" without support or warranty. Due to lack of time, I check this tracker once every few months. If you need help with an issue, consider posting the issue on Linux Mint forums where there are more people to help you out.
**Note:** This application is provided "as-is" without support or warranty. If you need changes or additional features in the application, please download the source code, make the changes, test it properly, and then submit a pull request. The changes will be reviewed and merged in the next update.
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

8
.gitignore vendored
View File

@ -23,11 +23,7 @@ snap/
release/
debian/timeshift/
rpm/
debian/debhelper-build-stamp
debian/timeshift.debhelper.log
debian/timeshift.substvars
debian/files
debian/timeshift.debhelper.log
debian/timeshift.substvars

View File

@ -1,3 +1,3 @@
Copyright (C) 2013 Tony George (teejee2008@gmail.com)
Copyright (C) 2020 Tony George (teejeetech@gmail.com)

View File

@ -2,5 +2,19 @@
app_fullname="Timeshift"
app_name="timeshift"
pkg_name="timeshift"
pkg_version=$(dpkg-parsechangelog --show-field Version)
build_deb=1
build_rpm=0
build_arch=0
deb_arch="amd64 i386 arm64 armhf" # amd64 i386 arm64 armhf
rpm_arch="" # x86_64 i686
arch_arch="" # x86_64 i686
pkg_version=$(dpkg-parsechangelog --show-field Version)
git_origin="git@github.com:teejee2008/timeshift.git"

View File

@ -164,6 +164,12 @@ If the backup device is running out of space, try the following steps:
* EFI systems are fully supported. Ensure that the ***/boot/efi*** partition is mapped while restoring a snapshot. It will be mapped automatically if detected.
* If you are restoring from Live CD/USB, and your installed system uses EFI mode, then you must boot from Live CD/USB in EFI mode.
## Support
If you use Linux Mint and need support for an issue please use the [Linux Mint support forums](https://forums.linuxmint.com)
Issues reported on the Issue Tracker will be fixed during the next update. Please do not expect a response as the tracker is checked once a year when the app is being updated.
## Disclaimer
This program is free for personal and commercial use and comes with absolutely no warranty. You use this program entirely at your own risk. The author will not be liable for any damages arising from the use of this program. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
@ -175,20 +181,16 @@ You can contribute to this project in various ways:
- Submitting ideas, and reporting issues in the [tracker](https://github.com/teejee2008/timeshift/issues)
- Translating this application to other languages
- Contributing code changes by fixing issues and submitting a pull request
- Making a donation via PayPal or bitcoin, or signing-up as a patron on Patreon
- Making a donation via PayPal or bitcoin
## Donate
*Timeshift* is a non-commercial application. I work on it during my free time based on my requirements and interest. If you wish to support this project, you can make a donation for $10 or more via PayPal. Your contributions will help keep the project alive and support future development.
*Timeshift* is a non-commercial application. I work on it during my free time based on my requirements and interest. If you wish to support this project, you can make a donation for $10 or more via PayPal. Your contributions will help keep the project alive.
**PayPal** ~ If you find this application useful and wish to say thanks, you can buy me a coffee by making a donation with Paypal.
**PayPal**
[![](images/PayPal.png)](https://www.paypal.com/cgi-bin/webscr?business=teejeetech@gmail.com&cmd=_xclick&currency_code=USD&amount=10&item_name=Timeshift%20Donation)
**Patreon** ~ You can also sign up as a sponsor on [Patreon.com](https://www.patreon.com/teejeetech). As a patron you will get access to beta releases of new applications that I'm working on. You will also get news and updates about new features that are not published elsewhere.
[![](images/patreon.png)](https://www.patreon.com/bePatron?u=3059450)
**Bitcoin** ~ You can send bitcoins at this address or by scanning the QR code below:
```1KdEyJjkuEW8aZWjenf4x5uEeHo9VTYqio```

View File

@ -1,66 +0,0 @@
#!/bin/bash
for prog in pbuilder-dist make dpkg-source ; do
if sh -c "which $prog 2> /dev/null"; then true ; else echo "You don\'t have $prog, install it" ; exit ; fi
done
backup=`pwd`
DIR="$( cd "$( dirname "$0" )" && pwd )"
cd $DIR
. ./BUILD_CONFIG
sh build-source.sh
rm -fv release/${pkg_name}-*.deb
build_deb_for_dist() {
dist=$1
arch=$2
echo ""
echo "=========================================================================="
echo " build-deb.sh : $dist-$arch"
echo "=========================================================================="
echo ""
rm -rfv release/${arch}
mkdir -pv release/${arch}
echo "-------------------------------------------------------------------------"
pbuilder-dist $dist $arch build release/source/${pkg_name}*.dsc --buildresult release/$arch
if [ $? -ne 0 ]; then cd "$backup"; echo "Failed"; exit 1; fi
echo "--------------------------------------------------------------------------"
cp -pv --no-preserve=ownership release/${arch}/${pkg_name}*.deb release/${pkg_name}-v${pkg_version}-${arch}.deb
if [ $? -ne 0 ]; then cd "$backup"; echo "Failed"; exit 1; fi
echo "--------------------------------------------------------------------------"
}
arches=""
if [ -z $1 ]; then
arches="i386 amd64"
else
arches="$1"
fi
for arch in $arches
do
build_deb_for_dist xenial $arch
done
#build_deb_for_dist xenial i386
#build_deb_for_dist xenial amd64
#build_deb_for_dist stretch armel
#build_deb_for_dist stretch armhf
cd "$backup"

View File

@ -1,60 +0,0 @@
#!/bin/bash
for prog in pbuilder-dist make dpkg-source ; do
if sh -c "which $prog 2> /dev/null" ; then true ; else echo "You don\'t have $prog, install it" ; exit ; fi
done
backup=`pwd`
DIR="$( cd "$( dirname "$0" )" && pwd )"
cd $DIR
. ./BUILD_CONFIG
rm -vf release/*.run
rm -vf release/*.deb
arches=""
if [ -z $1 ]; then
arches="i386 amd64"
# build deb
sh build-deb.sh
else
arches="$1"
# build deb
sh build-deb.sh "$1"
fi
for arch in $arches
do
rm -rfv release/${arch}/files
mkdir -pv release/${arch}/files
echo ""
echo "=========================================================================="
echo " build-installers.sh : $arch"
echo "=========================================================================="
echo ""
dpkg-deb -x release/${pkg_name}-v${pkg_version}-${arch}.deb release/${arch}/files
if [ $? -ne 0 ]; then cd "$backup"; echo "Failed"; exit 1;fi
echo "--------------------------------------------------------------------------"
rm -rfv release/${arch}/${pkg_name}*.* # remove source files created by pbuilder
cp -pv --no-preserve=ownership release/sanity.config release/${arch}/sanity.config
sanity --generate --base-path release/${arch} --out-path release --arch ${arch} --xz
if [ $? -ne 0 ]; then cd "$backup"; echo "Failed"; exit 1; fi
mv -v release/*${arch}.run release/${pkg_name}-v${pkg_version}-${arch}.run
echo "--------------------------------------------------------------------------"
done
cp -vf release/*.run ../PACKAGES/
cp -vf release/*.deb ../PACKAGES/
cd "$backup"

View File

@ -1,50 +0,0 @@
#!/bin/bash
for prog in pbuilder-dist make dpkg-source ; do
if sh -c "which $prog 2> /dev/null"; then true ; else echo "You don\'t have $prog, install it" ; exit ; fi
done
backup=`pwd`
DIR="$( cd "$( dirname "$0" )" && pwd )"
cd "$DIR"
. ./BUILD_CONFIG
echo ""
echo "=========================================================================="
echo " build-source.sh"
echo "=========================================================================="
echo ""
echo "app_name: $app_name"
echo "pkg_name: $pkg_name"
echo "--------------------------------------------------------------------------"
# clean build dir
rm -rfv /tmp/builds
mkdir -pv /tmp/builds
make clean
rm -rfv release/source
mkdir -pv release/source
echo "--------------------------------------------------------------------------"
# build source package
dpkg-source --build ./
mv -vf ../$pkg_name*.dsc release/source/
mv -vf ../$pkg_name*.tar.xz release/source/
if [ $? -ne 0 ]; then cd "$backup"; echo "Failed"; exit 1; fi
echo "--------------------------------------------------------------------------"
# list files
ls -l release/source
echo "-------------------------------------------------------------------------"
cd "$backup"

27
debian/changelog vendored
View File

@ -1,3 +1,30 @@
timeshift (20.11.1) focal; urgency=medium
* Fix #631: Escape single quote in LUKS password when unlocking device
* Fix #626: Filters: Save filter order changes when clicking OK
* Fix #643: Filters: Save changes after Include/Exclude radio is toggled
* Fix #668: Filters: Save changes immediately after pattern is edited
* Fix #666: Filters: Save changes immediately after adding a pattern;
and before clicking Summary button
* Move config file to /etc/timeshift/timeshift.json
* Move default config to /etc/timeshift/default.json
* AppStream: Install only under /usr/share/metainfo. Don't install
under /usr/share/appdata/
* Remove unused functions and code
* pkexec: Don't pass DISPLAY and AUTHORITY in launcher script
-- Tony George <teejeetech@gmail.com> Sun, 15 Nov 2020 20:00:00 +0530
timeshift (20.03) xenial; urgency=medium
* Fix an issue with script execution

View File

@ -13,6 +13,12 @@ pot:
manpage:
cd src; make manpage
dist-release:
build
dist-deb:
build-deb amd64
clean:
cd src; make clean

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -38,7 +38,7 @@ using TeeJee.Misc;
public Main App;
public const string AppName = "Timeshift";
public const string AppShortName = "timeshift";
public const string AppVersion = "20.03";
public const string AppVersion = "20.11.1";
public const string AppAuthor = "Tony George";
public const string AppAuthorEmail = "teejeetech@gmail.com";
@ -56,7 +56,7 @@ public class AppConsole : GLib.Object {
set_locale();
LOG_TIMESTAMP = false;
if (args.length > 1) {
switch (args[1].down()) {
case "--help":

View File

@ -42,6 +42,7 @@ public class Main : GLib.Object{
public string share_folder = "";
public string rsnapshot_conf_path = "";
public string app_conf_path = "";
public string app_conf_path_old = "";
public string app_conf_path_default = "";
public bool first_run = false;
@ -270,10 +271,11 @@ public class Main : GLib.Object{
this.app_path = (File.new_for_path (args[0])).get_parent().get_path ();
this.share_folder = "/usr/share";
this.app_conf_path = "/etc/timeshift.json";
this.app_conf_path_default = "/etc/default/timeshift.json";
this.app_conf_path = "/etc/timeshift/timeshift.json";
this.app_conf_path_old = "/etc/timeshift.json";
this.app_conf_path_default = "/etc/timeshift/default.json";
//sys_root and sys_home will be initalized by update_partition_list()
// check if running locally ------------------------
string local_exec = args[0];
@ -3104,14 +3106,19 @@ public class Main : GLib.Object{
// check if first run -----------------------
var f = File.new_for_path(this.app_conf_path);
if (!f.query_exists()) {
file_copy(app_conf_path_default, app_conf_path);
if (file_exists(app_conf_path_old)){
// move old file
file_move(app_conf_path_old, app_conf_path);
}
else if (file_exists(app_conf_path_default)){
// copy default file
file_copy(app_conf_path_default, app_conf_path);
}
}
if (!f.query_exists()) {
set_first_run_flag();
return;
}
// load settings from config file --------------------------
var parser = new Json.Parser();
@ -3124,13 +3131,13 @@ public class Main : GLib.Object{
var config = node.get_object();
bool do_first_run = json_get_bool(config, "do_first_run", false); // false as default
btrfs_mode = json_get_bool(config, "btrfs_mode", false); // false as default
if (do_first_run){
set_first_run_flag();
}
btrfs_mode = json_get_bool(config, "btrfs_mode", false); // false as default
if (config.has_member("include_btrfs_home")){
include_btrfs_home_for_backup = json_get_bool(config, "include_btrfs_home", include_btrfs_home_for_backup);
}
@ -3170,6 +3177,7 @@ public class Main : GLib.Object{
exclude_list_user.clear();
if (config.has_member ("exclude")){
foreach (Json.Node jnode in config.get_array_member ("exclude").get_elements()) {
string path = jnode.get_string();
@ -3186,7 +3194,9 @@ public class Main : GLib.Object{
exclude_app_names.clear();
if (config.has_member ("exclude-apps")){
var apps = config.get_array_member("exclude-apps");
foreach (Json.Node jnode in apps.get_elements()) {
string name = jnode.get_string();

View File

@ -26,7 +26,6 @@ using Gtk;
using Gee;
using Json;
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.JsonHelper;
@ -38,7 +37,7 @@ using TeeJee.Misc;
public Main App;
public const string AppName = "Timeshift";
public const string AppShortName = "timeshift";
public const string AppVersion = "20.03";
public const string AppVersion = "20.11.1";
public const string AppAuthor = "Tony George";
public const string AppAuthorEmail = "teejeetech@gmail.com";
@ -72,6 +71,7 @@ public class AppGtk : GLib.Object {
}
private static void set_locale() {
log_debug("setting locale...");
Intl.setlocale(GLib.LocaleCategory.MESSAGES, "timeshift");
Intl.textdomain(GETTEXT_PACKAGE);
@ -107,6 +107,7 @@ public class AppGtk : GLib.Object {
}
public static string help_message() {
string msg = "\n%s v%s by Tony George (%s)\n".printf(AppName, AppVersion, AppAuthorEmail);
msg += "\n";
msg += _("Syntax") + ": timeshift-gtk [options]\n";
@ -123,6 +124,7 @@ public class AppGtk : GLib.Object {
public static void check_if_admin(){
if (!user_is_admin()){
var msg = _("Admin access is required to backup and restore system files.") + "\n";
msg += _("Please re-run the application as admin (using 'sudo' or 'su')");

View File

@ -121,6 +121,8 @@ class ExcludeBox : Gtk.Box{
}
treeview_update_item(ref iter, pattern);
save_changes();
});
// column
@ -155,6 +157,8 @@ class ExcludeBox : Gtk.Box{
}
treeview_update_item(ref iter, pattern);
save_changes();
});
// column
@ -206,6 +210,8 @@ class ExcludeBox : Gtk.Box{
}
model.set (iter, 0, pattern, -1);
save_changes();
});
}
@ -229,6 +235,8 @@ class ExcludeBox : Gtk.Box{
treeview_add_item(treeview, pattern); // don't strip
Main.first_snapshot_size = 0; //re-calculate
}
save_changes();
});
button = add_button(hbox, _("Add Files"), _("Add files"), size_group, null);
@ -258,6 +266,7 @@ class ExcludeBox : Gtk.Box{
button = add_button(hbox, _("Summary"), "", size_group, null);
button.clicked.connect(()=>{
save_changes();
new ExcludeListSummaryWindow(false);
});
}

View File

@ -250,7 +250,7 @@ class MainWindow : Gtk.Window{
// scrolled
var scrolled = new Gtk.ScrolledWindow(null, null);
scrolled.set_shadow_type (ShadowType.ETCHED_IN);
//scrolled.set_shadow_type (ShadowType.ETCHED_IN);
//scrolled.margin = 6;
//scrolled.margin_top = 0;
scrolled.hscrollbar_policy = Gtk.PolicyType.NEVER;
@ -298,7 +298,7 @@ class MainWindow : Gtk.Window{
// scrolled
scrolled = new Gtk.ScrolledWindow(null, null);
scrolled.set_shadow_type (ShadowType.ETCHED_IN);
//scrolled.set_shadow_type (ShadowType.ETCHED_IN);
scrolled.hscrollbar_policy = Gtk.PolicyType.NEVER;
scrolled.vscrollbar_policy = Gtk.PolicyType.NEVER;
scrolled.set_no_show_all(true);
@ -334,7 +334,7 @@ class MainWindow : Gtk.Window{
//vbox_free_space = vbox;
scrolled = new Gtk.ScrolledWindow(null, null);
scrolled.set_shadow_type (ShadowType.ETCHED_IN);
//scrolled.set_shadow_type (ShadowType.ETCHED_IN);
scrolled.hscrollbar_policy = Gtk.PolicyType.NEVER;
scrolled.vscrollbar_policy = Gtk.PolicyType.NEVER;
scrolled.set_no_show_all(true);

View File

@ -126,6 +126,7 @@ class SettingsWindow : Gtk.Window{
bbox.add(btn_ok);
btn_ok.clicked.connect(()=>{
save_changes();
this.destroy();
});

View File

@ -221,7 +221,7 @@ class SnapshotListBox : Gtk.Box{
//cell_desc
col_desc = new TreeViewColumn();
col_desc.title = _("Comments");
col_desc.title = _("Comments (click to edit)");
col_desc.resizable = true;
col_desc.clickable = true;
col_desc.expand = true;

View File

@ -1,83 +0,0 @@
/*
* ArchiveFile.vala
*
* Copyright 2012-2018 Tony George <teejeetech@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
using GLib;
using Gtk;
using Gee;
using Json;
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.JsonHelper;
using TeeJee.ProcessHelper;
using TeeJee.GtkHelper;
using TeeJee.System;
using TeeJee.Misc;
public class ArchiveFile : FileItem {
// additional properties
public int64 archive_size = 0;
public int64 archive_unpacked_size = 0;
public double compression_ratio = 0.0;
public string archive_type = "";
public string archive_method = "";
public bool archive_is_encrypted = false;
public bool archive_is_solid = false;
public int archive_blocks = 0;
public int64 archive_header_size = 0;
public DateTime archive_modified;
public string password = "";
public string keyfile = "";
// extraction
public Gee.ArrayList<string> extract_list;
// temp
public string temp_dir = "";
public string script_file = "";
public string log_file = "";
public ArchiveFile(string archive_file_path = "") {
base.from_path_and_type(archive_file_path, FileType.REGULAR);
is_archive = true;
//this.tag = this;
extract_list = new Gee.ArrayList<string>();
temp_dir = TEMP_DIR + "/" + timestamp_for_path();
log_file = temp_dir + "/log.txt";
script_file = temp_dir + "/convert.sh";
dir_create (temp_dir);
}
public void add_items(Gee.ArrayList<string> item_list){
if (item_list.size > 0){
foreach(string item in item_list){
add_child_from_disk(item);
}
}
}
}

View File

@ -74,6 +74,7 @@ public abstract class AsyncTask : GLib.Object{
public signal void task_complete();
protected AsyncTask(){
working_dir = TEMP_DIR + "/" + timestamp_for_path();
script_file = path_combine(working_dir, "script.sh");
log_file = path_combine(working_dir, "task.log");
@ -258,6 +259,7 @@ public abstract class AsyncTask : GLib.Object{
protected abstract void parse_stderr_line(string err_line);
private void finish(){
// finish() gets called by 2 threads but should be executed only once
if (finish_called) { return; }
finish_called = true;
@ -317,6 +319,7 @@ public abstract class AsyncTask : GLib.Object{
protected abstract void finish_task();
protected int read_exit_code(){
exit_code = -1;
var path = file_parent(script_file) + "/status";
if (file_exists(path)){
@ -328,12 +331,14 @@ public abstract class AsyncTask : GLib.Object{
}
public bool is_running(){
return (status == AppStatus.RUNNING);
}
// public actions --------------
public void pause() {
Pid sub_child_pid;
foreach (long pid in get_process_children(child_pid)) {
sub_child_pid = (Pid) pid;
@ -344,6 +349,7 @@ public abstract class AsyncTask : GLib.Object{
}
public void resume() {
Pid sub_child_pid;
foreach (long pid in get_process_children(child_pid)) {
sub_child_pid = (Pid) pid;
@ -354,6 +360,7 @@ public abstract class AsyncTask : GLib.Object{
}
public void stop(AppStatus status_to_update = AppStatus.CANCELLED) {
// we need to un-freeze the processes before we kill them
if (status == AppStatus.PAUSED) {
resume();
@ -367,6 +374,7 @@ public abstract class AsyncTask : GLib.Object{
}
public void set_priority() {
if (background_mode){
set_priority_value(5);
}
@ -376,6 +384,7 @@ public abstract class AsyncTask : GLib.Object{
}
public void set_priority_value(int prio) {
Pid app_pid = Posix.getpid();
process_set_priority (app_pid, prio);
@ -414,6 +423,7 @@ public abstract class AsyncTask : GLib.Object{
}
public void print_app_status(){
switch(status){
case AppStatus.NOT_STARTED:
log_debug("status=%s".printf("NOT_STARTED"));

View File

@ -1,133 +0,0 @@
/*
* Bash.vala
*
* Copyright 2012-2018 Tony George <teejeetech@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
using GLib;
using Gtk;
using Gee;
using Json;
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.JsonHelper;
using TeeJee.ProcessHelper;
using TeeJee.GtkHelper;
using TeeJee.System;
using TeeJee.Misc;
public class Bash : AsyncTask {
public Pid bash_pid = -1;
public int status_code = -1;
private static Gee.HashMap<string, Regex> regex_list;
public Bash() {
init_regular_expressions();
}
private static void init_regular_expressions(){
if (regex_list != null){
return; // already initialized
}
regex_list = new Gee.HashMap<string,Regex>();
try {
//Example: status=-1
regex_list["status"] = new Regex("""status=([0-9\-]+)""");
}
catch (Error e) {
log_error (e.message);
}
}
// execution ----------------------------
public void start_shell() {
dir_create(working_dir);
var sh = "bash -c 'pkexec bash'";
save_bash_script_temp(sh, script_file);
begin();
log_debug("Started bash shell");
if (status == AppStatus.RUNNING){
bash_pid = -1;
while ((status == AppStatus.RUNNING) && (bash_pid == -1)) {
sleep(200);
var children = get_process_children(child_pid);
if (children.length > 0){
bash_pid = children[0];
}
}
log_debug("script pid: %d".printf(child_pid));
log_debug("bash shell pid: %d".printf(bash_pid));
}
}
public override void parse_stdout_line(string out_line){
if ((out_line == null) || (out_line.length == 0)) {
return;
}
MatchInfo match;
if (regex_list["status"].match(out_line, 0, out match)) {
status_code = int.parse(match.fetch(1));
}
stdout.printf(out_line + "\n");
stdout.flush();
}
public override void parse_stderr_line(string err_line){
stdout.printf(err_line + "\n");
stdout.flush();
}
public int execute(string line){
status_code = -1;
write_stdin(line);
write_stdin("echo status=$?");
while (status_code == -1){
sleep(200);
gtk_do_events();
}
return status_code;
}
protected override void finish_task(){
log_debug("Bash: finish_task()");
}
public int read_status(){
var status_file = working_dir + "/status";
var f = File.new_for_path(status_file);
if (f.query_exists()){
var txt = file_read(status_file);
return int.parse(txt);
}
return -1;
}
}

View File

@ -31,6 +31,7 @@ using TeeJee.System;
using TeeJee.Misc;
public class CryptTabEntry : GLib.Object{
public bool is_comment = false;
public bool is_empty_line = false;
@ -56,6 +57,7 @@ public class CryptTabEntry : GLib.Object{
}
public static Gee.ArrayList<CryptTabEntry> read_file(string file_path){
var list = new Gee.ArrayList<CryptTabEntry>();
if (!file_exists(file_path)){ return list; }
@ -103,9 +105,7 @@ public class CryptTabEntry : GLib.Object{
return list;
}
public static string write_file(
Gee.ArrayList<CryptTabEntry> entries, string file_path,
bool keep_comments_and_empty_lines = true){
public static string write_file(Gee.ArrayList<CryptTabEntry> entries, string file_path, bool keep_comments_and_empty_lines = true){
string text = "";
foreach(var entry in entries){

View File

@ -1423,9 +1423,9 @@ public class Device : GLib.Object{
// use password to unlock
var cmd = "echo -n -e '%s' | cryptsetup luksOpen --key-file - '%s' '%s'\n".printf(
luks_pass, luks_device.device, luks_name);
escape_single_quote(luks_pass), luks_device.device, luks_name);
log_debug(cmd.replace(luks_pass, "**PASSWORD**"));
log_debug(cmd.replace(escape_single_quote(luks_pass), "**PASSWORD**"));
int status = exec_script_sync(cmd, out std_out, out std_err, false, true);
@ -1469,9 +1469,9 @@ public class Device : GLib.Object{
// use password to unlock
var cmd = "echo -n -e '%s' | cryptsetup luksOpen --key-file - '%s' '%s'\n".printf(
luks_pass, luks_device.device, luks_name);
escape_single_quote(luks_pass), luks_device.device, luks_name);
log_debug(cmd.replace(luks_pass, "**PASSWORD**"));
log_debug(cmd.replace(escape_single_quote(luks_pass), "**PASSWORD**"));
int status = exec_script_sync(cmd, out std_out, out std_err, false, true);
@ -1515,6 +1515,7 @@ public class Device : GLib.Object{
}
public static bool luks_lock(string kname, Gtk.Window? parent_window){
var cmd = "cryptsetup luksClose %s".printf(kname);
log_debug(cmd);

View File

@ -51,65 +51,19 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
public bool is_selected = false;
public bool is_symlink = false;
public string symlink_target = "";
public bool is_archive = false;
public bool is_stale = false;
public FileItem parent;
public Gee.HashMap<string, FileItem> children = new Gee.HashMap<string, FileItem>();
public FileItem? source_archive;
public GLib.Object? tag;
//public Gtk.TreeIter? treeiter;
public long file_count = 0;
public long dir_count = 0;
private int64 _size = 0;
private int64 _size_compressed = 0;
public long file_count_total = 0;
public long dir_count_total = 0;
//public string icon_name = "gtk-file";
public GLib.Icon icon;
public bool is_dummy = false;
public static string[] archive_extensions = {
".tar",
".tar.gz", ".tgz",
".tar.bzip2", ".tar.bz2", ".tbz", ".tbz2", ".tb2",
".tar.lzma", ".tar.lz", ".tlz",
".tar.xz", ".txz",
".tar.7z",
".tar.zip",
".7z", ".lzma",
".bz2", ".bzip2",
".gz", ".gzip",
".zip", ".rar", ".cab", ".arj", ".z", ".taz", ".cpio",
".rpm", ".deb",
".lzh", ".lha",
".chm", ".chw", ".hxs",
".iso", ".dmg", ".xar", ".hfs", ".ntfs", ".fat", ".vhd", ".mbr",
".wim", ".swm", ".squashfs", ".cramfs", ".scap"
};
// contructors -------------------------------
public FileItem(string name = "New Archive") {
public FileItem(string name) {
file_name = name;
}
public FileItem.dummy(FileType _file_type) {
is_dummy = true;
file_type = _file_type;
}
public FileItem.dummy_root() {
file_name = "dummy";
file_location = "";
}
public FileItem.from_disk_path_with_basic_info(string _file_path) {
file_path = _file_path;
file_name = file_basename(_file_path);
@ -124,7 +78,7 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
file_type = _file_type;
}
// properties --------------------------------------
// properties -------------------------------------------------
public int64 size {
get{
@ -132,13 +86,7 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
}
}
public int64 size_compressed {
get{
return _size_compressed;
}
}
// helpers ---------------
// helpers ----------------------------------------------------
public int compare_to(FileItem b){
if (this.file_type != b.file_type) {
@ -159,211 +107,8 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
}
}
// instance methods ------------------------------------------
public FileItem add_child_from_disk(string item_file_path, int depth = -1) {
FileItem item = null;
//log_debug("add_child_from_disk: %02d: %s".printf(depth, item_file_path));
try {
FileEnumerator enumerator;
FileInfo info;
File file = File.parse_name (item_file_path);
if (file.query_exists()) {
// query file type
var item_file_type = file.query_file_type(FileQueryInfoFlags.NONE);
//add item
item = this.add_child(item_file_path, item_file_type, 0, 0, true);
if ((item.file_type == FileType.DIRECTORY) && !item.is_symlink) {
if (depth != 0){
//recurse children
enumerator = file.enumerate_children ("%s".printf(FileAttribute.STANDARD_NAME), 0);
while ((info = enumerator.next_file()) != null) {
string child_path = "%s/%s".printf(item_file_path, info.get_name());
item.add_child_from_disk(child_path, depth - 1);
}
}
}
}
}
catch (Error e) {
log_error (e.message);
}
return item;
}
public FileItem add_descendant(
string _file_path,
FileType ? _file_type,
int64 item_size,
int64 item_size_compressed) {
//log_debug("add_descendant=%s".printf(_file_path));
string item_path = _file_path.strip();
FileType item_type = (_file_type == null) ? FileType.REGULAR : _file_type;
if (item_path.has_suffix("/")) {
item_path = item_path[0:item_path.length - 1];
item_type = FileType.DIRECTORY;
}
if (item_path.has_prefix("/")) {
item_path = item_path[1:item_path.length];
}
string dir_name = "";
string dir_path = "";
//create dirs and find parent dir
FileItem current_dir = this;
string[] arr = item_path.split("/");
for (int i = 0; i < arr.length - 1; i++) {
//get dir name
dir_name = arr[i];
//add dir
if (!current_dir.children.keys.contains(dir_name)) {
if ((current_dir == this) && current_dir.is_archive){
dir_path = "";
}
else {
dir_path = current_dir.file_path + "/";
}
dir_path = "%s%s".printf(dir_path, dir_name);
current_dir.add_child(dir_path, FileType.DIRECTORY, 0, 0, false);
}
current_dir = current_dir.children[dir_name];
}
//get item name
string item_name = arr[arr.length - 1];
//add item
if (!current_dir.children.keys.contains(item_name)) {
//log_debug("add_descendant: add_child()");
current_dir.add_child(
item_path, item_type, item_size, item_size_compressed, false);
}
//log_debug("add_descendant: finished: %s".printf(item_path));
return current_dir.children[item_name];
}
public FileItem add_child(
string item_file_path,
FileType item_file_type,
int64 item_size,
int64 item_size_compressed,
bool item_query_file_info){
// create new item ------------------------------
//log_debug("add_child: %s".printf(item_file_path));
FileItem item = new FileItem.from_path_and_type(item_file_path, item_file_type);
//item.tag = this.tag;
foreach(var ext in archive_extensions){
if (item_file_path.has_suffix(ext)) {
item = new ArchiveFile(item_file_path);
item.is_archive = true;
break;
}
}
// check existing ----------------------------
bool existing_file = false;
if (!children.has_key(item.file_name)){
children[item.file_name] = item;
//set parent
item.parent = this;
}
else{
existing_file = true;
item = this.children[item.file_name];
// mark as fresh
item.is_stale = false;
}
// copy prefix from parent
item.file_path_prefix = this.file_path_prefix;
// query file properties
if (item_query_file_info){
//log_debug("add_child: query_file_info()");
item.query_file_info();
}
if (item_file_type == FileType.REGULAR) {
//log_debug("add_child: regular file");
// set file sizes
if (item_size > 0) {
item._size = item_size;
}
if (item_size_compressed > 0) {
item._size_compressed = item_size_compressed;
}
// update file counts
if (!existing_file){
this.file_count++;
this.file_count_total++;
this._size += item_size;
this._size_compressed += item_size_compressed;
// update file count and size of parent dirs
var temp = this;
while (temp.parent != null) {
temp.parent.file_count_total++;
temp.parent._size += item_size;
temp.parent._size_compressed += item_size_compressed;
temp = temp.parent;
}
}
}
else if (item_file_type == FileType.DIRECTORY) {
//log_debug("add_child: directory");
if (!existing_file){
// instance methods -------------------------------------------
// update dir counts
this.dir_count++;
this.dir_count_total++;
//this.size += _size;
//size will be updated when children are added
// update dir count of parent dirs
var temp = this;
while (temp.parent != null) {
temp.parent.dir_count_total++;
temp = temp.parent;
}
}
}
//log_debug("add_child: finished: fc=%lld dc=%lld path=%s".printf(
// file_count, dir_count, item_file_path));
return item;
}
public void query_file_info() {
try {
@ -378,7 +123,7 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
FileAttribute.STANDARD_TYPE,
FileAttribute.STANDARD_ICON,
FileAttribute.STANDARD_SYMLINK_TARGET),
FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
var item_file_type = info.get_file_type();
@ -477,186 +222,7 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
}
}
public void query_children(int depth = -1) {
FileEnumerator enumerator;
FileInfo info;
File file = File.parse_name (file_path);
if (!file.query_exists()) {
return;
}
if (file_type == FileType.DIRECTORY) {
if (depth == 0){
return;
}
try{
// mark existing children as stale
foreach(var child in children.values){
child.is_stale = true;
}
// recurse children
enumerator = file.enumerate_children ("%s".printf(FileAttribute.STANDARD_NAME), 0);
while ((info = enumerator.next_file()) != null) {
string child_name = info.get_name();
string child_path = GLib.Path.build_filename(file_path, child_name);
this.add_child_from_disk(child_path, depth - 1);
}
// remove stale children
var list = new Gee.ArrayList<string>();
foreach(var key in children.keys){
if (children[key].is_stale){
list.add(key);
}
}
foreach(var key in list){
//log_debug("Unset:%s".printf(key));
children.unset(key);
}
}
catch (Error e) {
log_error (e.message);
}
}
}
public void clear_children() {
this.children.clear();
}
public FileItem remove_child(string child_name) {
FileItem child = null;
if (this.children.has_key(child_name)) {
child = this.children[child_name];
this.children.unset(child_name);
if (child.file_type == FileType.REGULAR) {
//update file counts
this.file_count--;
this.file_count_total--;
//subtract child size
this._size -= child.size;
this._size_compressed -= child.size_compressed;
//update file count and size of parent dirs
var temp = this;
while (temp.parent != null) {
temp.parent.file_count_total--;
temp.parent._size -= child.size;
temp.parent._size_compressed -= child.size_compressed;
temp = temp.parent;
}
}
else {
//update dir counts
this.dir_count--;
this.dir_count_total--;
//subtract child counts
this.file_count_total -= child.file_count_total;
this.dir_count_total -= child.dir_count_total;
this._size -= child.size;
this._size_compressed -= child.size_compressed;
//update dir count of parent dirs
var temp = this;
while (temp.parent != null) {
temp.parent.dir_count_total--;
temp.parent.file_count_total -= child.file_count_total;
temp.parent.dir_count_total -= child.dir_count_total;
temp.parent._size -= child.size;
temp.parent._size_compressed -= child.size_compressed;
temp = temp.parent;
}
}
}
//log_debug("%3ld %3ld %s".printf(file_count, dir_count, file_path));
return child;
}
public FileItem? find_descendant(string path){
var child = this;
foreach(var part in path.split("/")){
// query children if needed
if (child.children.size == 0){
child.query_children(1);
if (child.children.size == 0){
break;
}
}
if (child.children.has_key(part)){
child = child.children[part];
}
}
if (child.file_path == path){
return child;
}
else{
return null;
}
}
public void set_file_path_prefix(string prefix){
file_path_prefix = prefix;
foreach(var child in this.children.values){
child.set_file_path_prefix(prefix);
}
}
public void print(int level) {
if (level == 0) {
stdout.printf("\n");
stdout.flush();
}
stdout.printf("%s%s\n".printf(string.nfill(level * 2, ' '), file_name));
stdout.flush();
foreach (var key in this.children.keys) {
this.children[key].print(level + 1);
}
}
public Gee.ArrayList<FileItem> get_children_sorted(){
var list = new Gee.ArrayList<FileItem>();
foreach(string key in children.keys) {
var item = children[key];
list.add(item);
}
list.sort((a, b) => {
if ((a.file_type == FileType.DIRECTORY) && (b.file_type != FileType.DIRECTORY)){
return -1;
}
else if ((a.file_type != FileType.DIRECTORY) && (b.file_type == FileType.DIRECTORY)){
return 1;
}
else{
return strcmp(a.file_name.down(), b.file_name.down());
}
});
return list;
}
// icons
// icons ------------------------------------------------------
public Gdk.Pixbuf? get_icon(int icon_size, bool add_transparency, bool add_emblems){
@ -678,6 +244,3 @@ public class FileItem : GLib.Object,Gee.Comparable<FileItem> {
return pixbuf;
}
}

View File

@ -191,8 +191,7 @@ public class FsTabEntry : GLib.Object{
}
}
public static FsTabEntry? find_entry_by_mount_point(
Gee.ArrayList<FsTabEntry> entries, string mount_path){
public static FsTabEntry? find_entry_by_mount_point(Gee.ArrayList<FsTabEntry> entries, string mount_path){
foreach(var entry in entries){
if (entry.mount_point == mount_path){
@ -203,6 +202,7 @@ public class FsTabEntry : GLib.Object{
}
public Device? resolve_device(Gee.ArrayList<CryptTabEntry> crypttab, Gtk.Window? parent_window){
Device dev_fstab = null;
if (device_uuid.length > 0){
dev_fstab = Device.get_device_by_uuid(device_uuid);

View File

@ -82,23 +82,20 @@ public class DonationWindow : Gtk.Window {
add_label(msg);
msg = _("Since this a free application there is no dedicated support for this app. You can use the GitHub issue tracker for reporting issues, or post your questions on the Linux Mint forums. Please avoid reporting issues by email.");
msg = _("You can use the GitHub issue tracker for reporting issues, or post your questions on the Linux Mint forums. Please avoid reporting issues by email.");
add_label(msg);
hbox = add_vbox();
add_button(hbox, _("GitHub"),
"https://github.com/teejee2008/%s/issues".printf(appname.down()));
add_button(hbox, _("GitHub"), "https://github.com/teejee2008/%s/issues".printf(appname.down()));
if (has_wiki){
add_button(hbox, _("Wiki"),
"https://github.com/teejee2008/%s/wiki".printf(appname.down()));
add_button(hbox, _("Wiki"), "https://github.com/teejee2008/%s/wiki".printf(appname.down()));
}
add_button(hbox, _("Website"),
"https://teejeetech.in/");
add_button(hbox, _("Website"), "https://teejeetech.in/");
// close window ---------------------------------------------------------

View File

@ -53,8 +53,7 @@ namespace TeeJee.GtkHelper{
gtk_do_events ();
}
public void gtk_messagebox(
string title, string message, Gtk.Window? parent_win, bool is_error = false){
public void gtk_messagebox(string title, string message, Gtk.Window? parent_win, bool is_error = false){
/* Shows a simple message box */
@ -81,8 +80,7 @@ namespace TeeJee.GtkHelper{
dlg.destroy();
}
public string? gtk_inputbox(
string title, string message, Gtk.Window? parent_win, bool mask_password = false){
public string? gtk_inputbox(string title, string message, Gtk.Window? parent_win, bool mask_password = false){
/* Shows a simple input prompt */
@ -194,10 +192,7 @@ namespace TeeJee.GtkHelper{
return val;
}
public GLib.Object gtk_combobox_get_selected_object (
ComboBox combo,
int index,
GLib.Object default_value){
public GLib.Object gtk_combobox_get_selected_object (ComboBox combo, int index, GLib.Object default_value){
/* Conveniance function to get combobox value */
@ -230,6 +225,7 @@ namespace TeeJee.GtkHelper{
// styles ----------------
public static int CSS_AUTO_CLASS_INDEX = 0;
public static void gtk_apply_css(Gtk.Widget[] widgets, string css_style){
var css_provider = new Gtk.CssProvider();
var css = ".style_%d { %s }".printf(++CSS_AUTO_CLASS_INDEX, css_style);
@ -262,98 +258,12 @@ namespace TeeJee.GtkHelper{
return count;
}
public void gtk_stripe_row(
Gtk.CellRenderer cell,
bool odd_row,
string odd_color = "#F4F6F7",
string even_color = "#FFFFFF"){
if (cell is Gtk.CellRendererText){
(cell as Gtk.CellRendererText).background = odd_row ? odd_color : even_color;
}
else if (cell is Gtk.CellRendererPixbuf){
(cell as Gtk.CellRendererPixbuf).cell_background = odd_row ? odd_color : even_color;
}
}
public void gtk_treeview_redraw(Gtk.TreeView treeview){
var model = treeview.model;
treeview.model = null;
treeview.model = model;
}
// menu
public void gtk_menu_add_separator(Gtk.Menu menu){
Gdk.RGBA gray = Gdk.RGBA();
gray.parse ("rgba(200,200,200,1)");
// separator
var menu_item = new Gtk.SeparatorMenuItem();
menu_item.override_color (StateFlags.NORMAL, gray);
menu.append(menu_item);
}
public Gtk.MenuItem gtk_menu_add_item(
Gtk.Menu menu,
string label,
string tooltip,
Gtk.Image? icon_image,
Gtk.SizeGroup? sg_icon = null,
Gtk.SizeGroup? sg_label = null){
var menu_item = new Gtk.MenuItem();
menu.append(menu_item);
var box = new Gtk.Box(Orientation.HORIZONTAL, 3);
menu_item.add(box);
// add icon
if (icon_image == null){
var dummy = new Gtk.Label("");
box.add(dummy);
if (sg_icon != null){
sg_icon.add_widget(dummy);
}
}
else{
box.add(icon_image);
if (sg_icon != null){
sg_icon.add_widget(icon_image);
}
}
// add label
var lbl = new Gtk.Label(label);
lbl.xalign = (float) 0.0;
lbl.margin_right = 6;
box.add(lbl);
if (sg_label != null){
sg_label.add_widget(lbl);
}
box.set_tooltip_text(tooltip);
return menu_item;
}
// build ui
public Gtk.Label gtk_box_add_header(Gtk.Box box, string text){
var label = new Gtk.Label("<b>" + text + "</b>");
label.set_use_markup(true);
label.xalign = (float) 0.0;
label.margin_bottom = 6;
box.add(label);
return label;
}
// misc
public bool gtk_container_has_child(Gtk.Container container, Gtk.Widget widget){
@ -365,31 +275,6 @@ namespace TeeJee.GtkHelper{
return false;
}
private void text_view_append(Gtk.TextView view, string text){
TextIter iter;
view.buffer.get_end_iter(out iter);
view.buffer.insert(ref iter, text, text.length);
}
private void text_view_prepend(Gtk.TextView view, string text){
TextIter iter;
view.buffer.get_start_iter(out iter);
view.buffer.insert(ref iter, text, text.length);
}
private void text_view_scroll_to_end(Gtk.TextView view){
TextIter iter;
view.buffer.get_end_iter(out iter);
view.scroll_to_iter(iter, 0.0, false, 0.0, 0.0);
}
private void text_view_scroll_to_start(Gtk.TextView view){
TextIter iter;
view.buffer.get_start_iter(out iter);
view.scroll_to_iter(iter, 0.0, false, 0.0, 0.0);
}
// file chooser ----------------
public Gtk.FileFilter create_file_filter(string group_name, string[] patterns) {
@ -404,8 +289,7 @@ namespace TeeJee.GtkHelper{
// utility ------------------
// add_notebook
private Gtk.Notebook add_notebook(
Gtk.Box box, bool show_tabs = true, bool show_border = true){
private Gtk.Notebook add_notebook(Gtk.Box box, bool show_tabs = true, bool show_border = true){
// notebook
var book = new Gtk.Notebook();
@ -418,24 +302,8 @@ namespace TeeJee.GtkHelper{
return book;
}
// add_tab
private Gtk.Box add_tab(
Gtk.Notebook book, string title, int margin = 12, int spacing = 6){
// label
var label = new Gtk.Label(title);
// vbox
var vbox = new Gtk.Box(Gtk.Orientation.VERTICAL, spacing);
vbox.margin = margin;
book.append_page (vbox, label);
return vbox;
}
// add_treeview
private Gtk.TreeView add_treeview(Gtk.Box box,
Gtk.SelectionMode selection_mode = Gtk.SelectionMode.SINGLE){
private Gtk.TreeView add_treeview(Gtk.Box box, Gtk.SelectionMode selection_mode = Gtk.SelectionMode.SINGLE){
// TreeView
var treeview = new TreeView();
@ -455,8 +323,7 @@ namespace TeeJee.GtkHelper{
}
// add_column_text
private Gtk.TreeViewColumn add_column_text(
Gtk.TreeView treeview, string title, out Gtk.CellRendererText cell){
private Gtk.TreeViewColumn add_column_text(Gtk.TreeView treeview, string title, out Gtk.CellRendererText cell){
// TreeViewColumn
var col = new Gtk.TreeViewColumn();
@ -470,10 +337,8 @@ namespace TeeJee.GtkHelper{
return col;
}
// add_column_icon
private Gtk.TreeViewColumn add_column_icon(
Gtk.TreeView treeview, string title, out Gtk.CellRendererPixbuf cell){
private Gtk.TreeViewColumn add_column_icon(Gtk.TreeView treeview, string title, out Gtk.CellRendererPixbuf cell){
// TreeViewColumn
var col = new Gtk.TreeViewColumn();
@ -488,8 +353,7 @@ namespace TeeJee.GtkHelper{
}
// add_column_icon_and_text
private Gtk.TreeViewColumn add_column_icon_and_text(
Gtk.TreeView treeview, string title,
private Gtk.TreeViewColumn add_column_icon_and_text(Gtk.TreeView treeview, string title,
out Gtk.CellRendererPixbuf cell_pix, out Gtk.CellRendererText cell_text){
// TreeViewColumn
@ -509,8 +373,7 @@ namespace TeeJee.GtkHelper{
}
// add_column_radio_and_text
private Gtk.TreeViewColumn add_column_radio_and_text(
Gtk.TreeView treeview, string title,
private Gtk.TreeViewColumn add_column_radio_and_text(Gtk.TreeView treeview, string title,
out Gtk.CellRendererToggle cell_radio, out Gtk.CellRendererText cell_text){
// TreeViewColumn
@ -532,11 +395,8 @@ namespace TeeJee.GtkHelper{
}
// add_column_icon_radio_text
private Gtk.TreeViewColumn add_column_icon_radio_text(
Gtk.TreeView treeview, string title,
out Gtk.CellRendererPixbuf cell_pix,
out Gtk.CellRendererToggle cell_radio,
out Gtk.CellRendererText cell_text){
private Gtk.TreeViewColumn add_column_icon_radio_text(Gtk.TreeView treeview, string title,
out Gtk.CellRendererPixbuf cell_pix, out Gtk.CellRendererToggle cell_radio, out Gtk.CellRendererText cell_text){
// TreeViewColumn
var col = new Gtk.TreeViewColumn();
@ -561,9 +421,7 @@ namespace TeeJee.GtkHelper{
}
// add_label_scrolled
private Gtk.Label add_label_scrolled(
Gtk.Box box, string text,
bool show_border = false, bool wrap = false, int ellipsize_chars = 40){
private Gtk.Label add_label_scrolled(Gtk.Box box, string text, bool show_border = false, bool wrap = false, int ellipsize_chars = 40){
// ScrolledWindow
var scroll = new Gtk.ScrolledWindow(null, null);
@ -599,33 +457,8 @@ namespace TeeJee.GtkHelper{
return label;
}
// add_text_view
private Gtk.TextView add_text_view(
Gtk.Box box, string text){
// ScrolledWindow
var scrolled = new Gtk.ScrolledWindow(null, null);
scrolled.hscrollbar_policy = PolicyType.NEVER;
scrolled.vscrollbar_policy = PolicyType.ALWAYS;
scrolled.expand = true;
box.add(scrolled);
var view = new Gtk.TextView();
view.wrap_mode = Gtk.WrapMode.WORD_CHAR;
view.accepts_tab = false;
view.editable = false;
view.cursor_visible = false;
view.buffer.text = text;
view.sensitive = false;
scrolled.add (view);
return view;
}
// add_label
private Gtk.Label add_label(
Gtk.Box box, string text, bool bold = false,
bool italic = false, bool large = false){
private Gtk.Label add_label(Gtk.Box box, string text, bool bold = false, bool italic = false, bool large = false){
string msg = "<span%s%s%s>%s</span>".printf(
(bold ? " weight=\"bold\"" : ""),
@ -642,9 +475,7 @@ namespace TeeJee.GtkHelper{
return label;
}
private string format_text(
string text,
bool bold = false, bool italic = false, bool large = false){
private string format_text(string text, bool bold = false, bool italic = false, bool large = false){
string msg = "<span%s%s%s>%s</span>".printf(
(bold ? " weight=\"bold\"" : ""),
@ -656,8 +487,7 @@ namespace TeeJee.GtkHelper{
}
// add_label_header
private Gtk.Label add_label_header(
Gtk.Box box, string text, bool large_heading = false){
private Gtk.Label add_label_header(Gtk.Box box, string text, bool large_heading = false){
var label = add_label(box, escape_html(text), true, false, large_heading);
label.margin_bottom = 12;
@ -665,8 +495,7 @@ namespace TeeJee.GtkHelper{
}
// add_label_subnote
private Gtk.Label add_label_subnote(
Gtk.Box box, string text){
private Gtk.Label add_label_subnote(Gtk.Box box, string text){
var label = add_label(box, text, false, true);
label.margin_left = 6;
@ -674,8 +503,7 @@ namespace TeeJee.GtkHelper{
}
// add_radio
private Gtk.RadioButton add_radio(
Gtk.Box box, string text, Gtk.RadioButton? another_radio_in_group){
private Gtk.RadioButton add_radio(Gtk.Box box, string text, Gtk.RadioButton? another_radio_in_group){
Gtk.RadioButton radio = null;
@ -702,8 +530,7 @@ namespace TeeJee.GtkHelper{
}
// add_checkbox
private Gtk.CheckButton add_checkbox(
Gtk.Box box, string text){
private Gtk.CheckButton add_checkbox(Gtk.Box box, string text){
var chk = new Gtk.CheckButton.with_label(text);
chk.label = text;
@ -727,9 +554,7 @@ namespace TeeJee.GtkHelper{
}
// add_spin
private Gtk.SpinButton add_spin(
Gtk.Box box, double min, double max, double val,
int digits = 0, double step = 1, double step_page = 1){
private Gtk.SpinButton add_spin(Gtk.Box box, double min, double max, double val, int digits = 0, double step = 1, double step_page = 1){
var adj = new Gtk.Adjustment(val, min, max, step, step_page, 0);
var spin = new Gtk.SpinButton(adj, step, digits);
@ -746,10 +571,7 @@ namespace TeeJee.GtkHelper{
}
// add_button
private Gtk.Button add_button(
Gtk.Box box, string text, string tooltip,
Gtk.SizeGroup? size_group,
Gtk.Image? icon = null){
private Gtk.Button add_button(Gtk.Box box, string text, string tooltip, Gtk.SizeGroup? size_group, Gtk.Image? icon = null){
var button = new Gtk.Button();
box.add(button);
@ -770,10 +592,7 @@ namespace TeeJee.GtkHelper{
}
// add_toggle_button
private Gtk.ToggleButton add_toggle_button(
Gtk.Box box, string text, string tooltip,
Gtk.SizeGroup? size_group,
Gtk.Image? icon = null){
private Gtk.ToggleButton add_toggle_button(Gtk.Box box, string text, string tooltip, Gtk.SizeGroup? size_group, Gtk.Image? icon = null){
var button = new Gtk.ToggleButton();
box.add(button);
@ -794,8 +613,7 @@ namespace TeeJee.GtkHelper{
}
// add_directory_chooser
private Gtk.Entry add_directory_chooser(
Gtk.Box box, string selected_directory, Gtk.Window parent_window){
private Gtk.Entry add_directory_chooser(Gtk.Box box, string selected_directory, Gtk.Window parent_window){
// Entry
var entry = new Gtk.Entry();
@ -837,6 +655,5 @@ namespace TeeJee.GtkHelper{
return entry;
}
}

View File

@ -201,8 +201,7 @@ public class IconManager : GLib.Object {
return null;
}
public static Gdk.Pixbuf? add_emblem (Gdk.Pixbuf pixbuf, string icon_name, int emblem_size,
bool emblem_symbolic, Gtk.CornerType corner_type) {
public static Gdk.Pixbuf? add_emblem (Gdk.Pixbuf pixbuf, string icon_name, int emblem_size, bool emblem_symbolic, Gtk.CornerType corner_type) {
if (icon_name.length == 0){ return pixbuf; }

View File

@ -1,6 +1,6 @@
/*
* ProcStats.vala
* LinuxDistro.vala
*
* Copyright 2012-2018 Tony George <teejeetech@gmail.com>
*
@ -36,6 +36,7 @@ public class LinuxDistro : GLib.Object{
public string codename = "";
public LinuxDistro(){
dist_id = "";
description = "";
release = "";
@ -43,6 +44,7 @@ public class LinuxDistro : GLib.Object{
}
public string full_name(){
if (dist_id == ""){
return "";
}

View File

@ -14,6 +14,7 @@ public class MountEntry : GLib.Object{
public string mount_options = "";
public MountEntry(Device? device, string mount_point, string mount_options){
this.device = device;
this.mount_point = mount_point;
this.mount_options = mount_options;
@ -37,6 +38,7 @@ public class MountEntry : GLib.Object{
}
public string lvm_name(){
if ((device != null) && (device.type == "lvm") && (device.mapped_name.length > 0)){
return device.mapped_name.strip();
}
@ -45,14 +47,14 @@ public class MountEntry : GLib.Object{
}
}
public static MountEntry? find_entry_by_mount_point(
Gee.ArrayList<MountEntry> entries, string mount_path){
public static MountEntry? find_entry_by_mount_point(Gee.ArrayList<MountEntry> entries, string mount_path){
foreach(var entry in entries){
if (entry.mount_point == mount_path){
return entry;
}
}
return null;
}
}

View File

@ -28,6 +28,7 @@ using TeeJee.ProcessHelper;
// dep: notify-send
public class OSDNotify : GLib.Object {
private static DateTime dt_last_notification = null;
public const int NOTIFICATION_INTERVAL = 3;
@ -53,7 +54,9 @@ public class OSDNotify : GLib.Object {
}
long seconds = 9999;
if (dt_last_notification != null){
DateTime dt_end = new DateTime.now_local();
TimeSpan elapsed = dt_end.difference(dt_last_notification);
seconds = (long)(elapsed * 1.0 / TimeSpan.SECOND);
@ -79,12 +82,9 @@ public class OSDNotify : GLib.Object {
}
public static bool is_supported(){
string path = get_cmd_path ("notify-send");
if ((path != null) && (path.length > 0)){
return true;
}
else{
return false;
}
string path = get_cmd_path("notify-send");
return (path != null) && (path.length > 0);
}
}

View File

@ -1,89 +0,0 @@
/*
* ProcStats.vala
*
* Copyright 2012-2018 Tony George <teejeetech@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.ProcessHelper;
public class ProcStats : GLib.Object {
public double user = 0;
public double nice = 0;
public double system = 0;
public double idle = 0;
public double iowait = 0;
public double user_delta = 0;
public double nice_delta = 0;
public double system_delta = 0;
public double idle_delta = 0;
public double iowait_delta = 0;
public double usage_percent = 0;
public static ProcStats stat_prev = null;
public ProcStats(string line){
string[] arr = line.split(" ");
int col = 0;
if (arr[col++] == "cpu"){
if (arr[col].length == 0){ col++; };
user = double.parse(arr[col++]);
nice = double.parse(arr[col++]);
system = double.parse(arr[col++]);
idle = double.parse(arr[col++]);
iowait = double.parse(arr[col++]);
if (ProcStats.stat_prev != null){
user_delta = user - ProcStats.stat_prev.user;
nice_delta = nice - ProcStats.stat_prev.nice;
system_delta = system - ProcStats.stat_prev.system;
idle_delta = idle - ProcStats.stat_prev.idle;
iowait_delta = iowait - ProcStats.stat_prev.iowait;
usage_percent = (user_delta + nice_delta + system_delta) * 100 / (user_delta + nice_delta + system_delta + idle_delta);
}
else{
usage_percent = 0;
}
ProcStats.stat_prev = this;
}
}
//returns 0 when it is called first time
public static double get_cpu_usage(){
string txt = file_read("/proc/stat");
foreach(string line in txt.split("\n")){
string[] arr = line.split(" ");
if (arr[0] == "cpu"){
ProcStats stat = new ProcStats(line);
return stat.usage_percent;
}
}
return 0;
}
}

View File

@ -1,318 +0,0 @@
/*
* SystemGroup.vala
*
* Copyright 2012-2018 Tony George <teejeetech@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.ProcessHelper;
public class SystemGroup : GLib.Object {
public string name = "";
public string password = "";
public int gid = -1;
public string user_names = "";
public string shadow_line = "";
public string password_hash = "";
public string admin_list = "";
public string member_list = "";
public bool is_selected = false;
public Gee.ArrayList<string> users;
public static Gee.HashMap<string,SystemGroup> all_groups;
public SystemGroup(string name){
this.name = name;
this.users = new Gee.ArrayList<string>();
}
public static void query_groups(bool no_passwords = true){
if (no_passwords){
all_groups = read_groups_from_file("/etc/group","","");
}
else{
all_groups = read_groups_from_file("/etc/group","/etc/gshadow","");
}
}
public static Gee.ArrayList<SystemGroup> all_groups_sorted {
owned get {
var list = new Gee.ArrayList<SystemGroup>();
foreach(var group in all_groups.values) {
list.add(group);
}
list.sort((a,b) => { return strcmp(a.name, b.name); });
return list;
}
}
public bool is_installed{
get{
return SystemGroup.all_groups.has_key(name);
}
}
public static Gee.HashMap<string,SystemGroup> read_groups_from_file(string group_file, string gshadow_file, string password){
var list = new Gee.HashMap<string,SystemGroup>();
// read 'group' file -------------------------------
string txt = "";
if (group_file.has_suffix(".tar.gpg")){
txt = file_decrypt_untar_read(group_file, password);
}
else{
txt = file_read(group_file);
}
if (txt.length == 0){
return list;
}
foreach(string line in txt.split("\n")){
if ((line == null) || (line.length == 0)){
continue;
}
var group = parse_line_group(line);
if (group != null){
list[group.name] = group;
}
}
if (gshadow_file.length == 0){
return list;
}
// read 'gshadow' file -------------------------------
txt = "";
if (gshadow_file.has_suffix(".tar.gpg")){
txt = file_decrypt_untar_read(gshadow_file, password);
}
else{
txt = file_read(gshadow_file);
}
if (txt.length == 0){
return list;
}
foreach(string line in txt.split("\n")){
if ((line == null) || (line.length == 0)){
continue;
}
parse_line_gshadow(line, list);
}
return list;
}
private static SystemGroup? parse_line_group(string line){
if ((line == null) || (line.length == 0)){
return null;
}
SystemGroup group = null;
//cdrom:x:24:teejee,user2
string[] fields = line.split(":");
if (fields.length == 4){
group = new SystemGroup(fields[0].strip());
group.password = fields[1].strip();
group.gid = int.parse(fields[2].strip());
group.user_names = fields[3].strip();
foreach(string user_name in group.user_names.split(",")){
group.users.add(user_name);
}
}
else{
log_error("'group' file contains a record with non-standard fields" + ": %d".printf(fields.length));
return null;
}
return group;
}
private static SystemGroup? parse_line_gshadow(string line, Gee.HashMap<string,SystemGroup> list){
if ((line == null) || (line.length == 0)){
return null;
}
SystemGroup group = null;
//adm:*::syslog,teejee
//<groupname>:<encrypted-password>:<admins>:<members>
string[] fields = line.split(":");
if (fields.length == 4){
string group_name = fields[0].strip();
if (list.has_key(group_name)){
group = list[group_name];
group.shadow_line = line;
group.password_hash = fields[1].strip();
group.admin_list = fields[2].strip();
group.member_list = fields[3].strip();
return group;
}
else{
log_error("group in file 'gshadow' does not exist in file 'group'" + ": %s".printf(group_name));
return null;
}
}
else{
log_error("'gshadow' file contains a record with non-standard fields" + ": %d".printf(fields.length));
return null;
}
}
public static int add_group(string group_name, bool system_account = false){
string std_out, std_err;
string cmd = "groupadd%s %s".printf((system_account)? " --system" : "", group_name);
int status = exec_sync(cmd, out std_out, out std_err);
if (status != 0){
log_error(std_err);
}
else{
//log_msg(std_out);
}
return status;
}
public int add(){
return add_group(name,is_system);
}
public static int add_user_to_group(string user_name, string group_name){
string std_out, std_err;
string cmd = "adduser %s %s".printf(user_name, group_name);
log_debug(cmd);
int status = exec_sync(cmd, out std_out, out std_err);
if (status != 0){
log_error(std_err);
}
else{
//log_msg(std_out);
}
return status;
}
public int add_to_group(string user_name){
return add_user_to_group(user_name, name);
}
public bool is_system{
get {
return (gid < 1000);
}
}
public bool update_group_file(){
string file_path = "/etc/group";
string txt = file_read(file_path);
var txt_new = "";
foreach(string line in txt.split("\n")){
if (line.strip().length == 0) {
continue;
}
string[] parts = line.split(":");
if (parts.length != 4){
log_error("'group' file contains a record with non-standard fields" + ": %d".printf(parts.length));
return false;
}
if (parts[0].strip() == name){
txt_new += get_group_line() + "\n";
}
else{
txt_new += line + "\n";
}
}
file_write(file_path, txt_new);
log_msg("Updated group settings in /etc/group" + ": %s".printf(name));
return true;
}
public string get_group_line(){
string txt = "";
txt += "%s".printf(name);
txt += ":%s".printf(password);
txt += ":%d".printf(gid);
txt += ":%s".printf(user_names);
return txt;
}
public bool update_gshadow_file(){
string file_path = "/etc/gshadow";
string txt = file_read(file_path);
var txt_new = "";
foreach(string line in txt.split("\n")){
if (line.strip().length == 0) {
continue;
}
string[] parts = line.split(":");
if (parts.length != 4){
log_error("'gshadow' file contains a record with non-standard fields" + ": %d".printf(parts.length));
return false;
}
if (parts[0].strip() == name){
txt_new += get_gshadow_line() + "\n";
}
else{
txt_new += line + "\n";
}
}
file_write(file_path, txt_new);
log_msg("Updated group settings in /etc/gshadow" + ": %s".printf(name));
return true;
}
public string get_gshadow_line(){
string txt = "";
txt += "%s".printf(name);
txt += ":%s".printf(password_hash);
txt += ":%s".printf(admin_list);
txt += ":%s".printf(member_list);
return txt;
}
}

View File

@ -67,6 +67,7 @@ public class SystemUser : GLib.Object {
}
public static void query_users(bool no_passwords = true){
if (no_passwords){
all_users = read_users_from_file("/etc/passwd","","");
}
@ -93,20 +94,14 @@ public class SystemUser : GLib.Object {
}
public static Gee.HashMap<string,SystemUser> read_users_from_file(
string passwd_file, string shadow_file, string password){
var list = new Gee.HashMap<string,SystemUser>();
// read 'passwd' file ---------------------------------
string txt = "";
if (passwd_file.has_suffix(".tar.gpg")){
txt = file_decrypt_untar_read(passwd_file, password);
}
else{
txt = file_read(passwd_file);
}
string txt = file_read(passwd_file);
if (txt.length == 0){
return list;
@ -128,14 +123,7 @@ public class SystemUser : GLib.Object {
// read 'shadow' file ---------------------------------
txt = "";
if (shadow_file.has_suffix(".tar.gpg")){
txt = file_decrypt_untar_read(shadow_file, password);
}
else{
txt = file_read(shadow_file);
}
txt = file_read(shadow_file);
if (txt.length == 0){
return list;
@ -152,6 +140,7 @@ public class SystemUser : GLib.Object {
}
private static SystemUser? parse_line_passwd(string line){
if ((line == null) || (line.length == 0)){
return null;
}
@ -198,6 +187,7 @@ public class SystemUser : GLib.Object {
}
private static SystemUser? parse_line_shadow(string line, Gee.HashMap<string,SystemUser> list){
if ((line == null) || (line.length == 0)){
return null;
}
@ -235,24 +225,6 @@ public class SystemUser : GLib.Object {
}
}
public static int add_user(string user_name, bool system_account = false){
string std_out, std_err;
string cmd = "adduser%s --gecos '' --disabled-login %s".printf((system_account ? " --system" : ""), user_name);
log_debug(cmd);
int status = exec_sync(cmd, out std_out, out std_err);
if (status != 0){
log_error(std_err);
}
else{
//log_msg(std_out);
}
return status;
}
public int add(){
return add_user(name, is_system);
}
public void check_encrypted_dirs() {
// check encrypted home ------------------------------
@ -312,96 +284,5 @@ public class SystemUser : GLib.Object {
return "";
}
}
public bool update_passwd_file(){
string file_path = "/etc/passwd";
string txt = file_read(file_path);
var txt_new = "";
foreach(string line in txt.split("\n")){
if (line.strip().length == 0) {
continue;
}
string[] parts = line.split(":");
if (parts.length != 7){
log_error("'passwd' file contains a record with non-standard fields" + ": %d".printf(parts.length));
return false;
}
if (parts[0].strip() == name){
txt_new += get_passwd_line() + "\n";
}
else{
txt_new += line + "\n";
}
}
file_write(file_path, txt_new);
log_msg("Updated user settings in /etc/passwd" + ": %s".printf(name));
return true;
}
public string get_passwd_line(){
string txt = "";
txt += "%s".printf(name);
txt += ":%s".printf(password);
txt += ":%d".printf(uid);
txt += ":%d".printf(gid);
txt += ":%s".printf(user_info);
txt += ":%s".printf(home_path);
txt += ":%s".printf(shell_path);
return txt;
}
public bool update_shadow_file(){
string file_path = "/etc/shadow";
string txt = file_read(file_path);
var txt_new = "";
foreach(string line in txt.split("\n")){
if (line.strip().length == 0) {
continue;
}
string[] parts = line.split(":");
if (parts.length != 9){
log_error("'shadow' file contains a record with non-standard fields" + ": %d".printf(parts.length));
return false;
}
if (parts[0].strip() == name){
txt_new += get_shadow_line() + "\n";
}
else{
txt_new += line + "\n";
}
}
file_write(file_path, txt_new);
log_msg("Updated user settings in /etc/shadow" + ": %s".printf(name));
return true;
}
public string get_shadow_line(){
string txt = "";
txt += "%s".printf(name);
txt += ":%s".printf(pwd_hash);
txt += ":%s".printf(pwd_last_changed);
txt += ":%s".printf(pwd_age_min);
txt += ":%s".printf(pwd_age_max);
txt += ":%s".printf(pwd_warning_period);
txt += ":%s".printf(pwd_inactivity_period);
txt += ":%s".printf(pwd_expiraton_date);
txt += ":%s".printf(reserved_field);
return txt;
}
}

View File

@ -102,28 +102,6 @@ namespace TeeJee.FileSystem{
}
}
public bool file_move_to_trash(string file_path){
/* Check and delete file */
var file = File.new_for_path (file_path);
if (file.query_exists ()) {
Posix.system("gvfs-trash '%s'".printf(escape_single_quote(file_path)));
}
return true;
}
public bool file_shred(string file_path){
/* Check and delete file */
var file = File.new_for_path (file_path);
if (file.query_exists ()) {
Posix.system("shred -u '%s'".printf(escape_single_quote(file_path)));
}
return true;
}
public int64 file_line_count (string file_path){
/* Count number of lines in text file */
string cmd = "wc -l '%s'".printf(escape_single_quote(file_path));
@ -397,10 +375,6 @@ namespace TeeJee.FileSystem{
return (status == 0);
}
public bool dir_move_to_trash (string dir_path){
return file_move_to_trash(dir_path);
}
public bool dir_is_empty (string dir_path){
/* Check if directory is empty */
@ -425,6 +399,7 @@ namespace TeeJee.FileSystem{
}
public bool filesystem_supports_hardlinks(string path, out bool is_readonly){
bool supports_hardlinks = false;
is_readonly = false;
@ -469,6 +444,7 @@ namespace TeeJee.FileSystem{
}
public Gee.ArrayList<string> dir_list_names(string path){
var list = new Gee.ArrayList<string>();
try
@ -494,69 +470,6 @@ namespace TeeJee.FileSystem{
return list;
}
public bool dir_tar (string src_dir, string tar_file, bool recursion = true){
if (dir_exists(src_dir)) {
if (file_exists(tar_file)){
file_delete(tar_file);
}
var src_parent = file_parent(src_dir);
var src_name = file_basename(src_dir);
string cmd = "tar cvf '%s' --overwrite --%srecursion -C '%s' '%s'\n".printf(
escape_single_quote(tar_file),
(recursion ? "" : "no-"),
escape_single_quote(src_parent),
escape_single_quote(src_name));
log_debug(cmd);
string stdout, stderr;
int status = exec_script_sync(cmd, out stdout, out stderr);
if (status == 0){
return true;
}
else{
log_msg(stderr);
}
}
else{
log_error(_("Dir not found") + ": %s".printf(src_dir));
}
return false;
}
public bool dir_untar (string tar_file, string dst_dir){
if (file_exists(tar_file)) {
if (!dir_exists(dst_dir)){
dir_create(dst_dir);
}
string cmd = "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(
escape_single_quote(tar_file),
escape_single_quote(dst_dir));
log_debug(cmd);
string stdout, stderr;
int status = exec_script_sync(cmd, out stdout, out stderr);
if (status == 0){
return true;
}
else{
log_msg(stderr);
}
}
else{
log_error(_("File not found") + ": %s".printf(tar_file));
}
return false;
}
public bool chown(string dir_path, string user, string group = user){
string cmd = "chown %s:%s -R '%s'".printf(user, group, escape_single_quote(dir_path));
int status = exec_sync(cmd, null, null);
@ -599,154 +512,6 @@ namespace TeeJee.FileSystem{
return (long)(dir_size(path) / 1024.0);
}
// archiving and encryption ----------------
// dep: tar gzip gpg
public bool file_tar_encrypt (string src_file, string dst_file, string password){
if (file_exists(src_file)) {
if (file_exists(dst_file)){
file_delete(dst_file);
}
var src_dir = file_parent(src_file);
var src_name = file_basename(src_file);
var dst_dir = file_parent(dst_file);
var dst_name = file_basename(dst_file);
var tar_name = dst_name[0 : dst_name.index_of(".gpg")];
var tar_file = "%s/%s".printf(dst_dir, tar_name);
string cmd = "tar cvf '%s' --overwrite -C '%s' '%s'\n".printf(
escape_single_quote(tar_file),
escape_single_quote(src_dir),
escape_single_quote(src_name));
cmd += "gpg --passphrase '%s' -o '%s' --symmetric '%s'\n".printf(
password,
escape_single_quote(dst_file),
escape_single_quote(tar_file));
cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
log_debug(cmd);
string stdout, stderr;
int status = exec_script_sync(cmd, out stdout, out stderr);
if (status == 0){
return true;
}
else{
log_msg(stderr);
}
}
return false;
}
// dep: tar gzip gpg
public string file_decrypt_untar_read (string src_file, string password){
if (file_exists(src_file)) {
//var src_name = file_basename(src_file);
//var tar_name = src_name[0 : src_name.index_of(".gpg")];
//var tar_file = "%s/%s".printf(TEMP_DIR, tar_name);
//var temp_file = "%s/%s".printf(TEMP_DIR, random_string());
string cmd = "";
cmd += "gpg --quiet --no-verbose --passphrase '%s' -o- --decrypt '%s'".printf(
password,
escape_single_quote(src_file));
cmd += " | tar xf - --to-stdout 2>/dev/null\n";
cmd += "exit $?\n";
log_debug(cmd);
string std_out, std_err;
int status = exec_script_sync(cmd, out std_out, out std_err);
if (status == 0){
return std_out;
}
else{
log_error(std_err);
return "";
}
}
else{
log_error(_("File is missing") + ": %s".printf(src_file));
}
return "";
}
// dep: tar gzip gpg
public bool decrypt_and_untar (string src_file, string dst_file, string password){
if (file_exists(src_file)) {
if (file_exists(dst_file)){
file_delete(dst_file);
}
var src_dir = file_parent(src_file);
var src_name = file_basename(src_file);
var tar_name = src_name[0 : src_name.index_of(".gpg")];
var tar_file = "%s/%s".printf(src_dir, tar_name);
string cmd = "";
// gpg cannot overwrite - remove tar file if it exists
cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
cmd += "gpg --passphrase '%s' -o '%s' --decrypt '%s'\n".printf(
password,
escape_single_quote(tar_file),
escape_single_quote(src_file));
cmd += "status=$?; if [ $status -ne 0 ]; then exit $status; fi\n";
cmd += "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(
escape_single_quote(tar_file),
escape_single_quote(file_parent(dst_file)));
cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
log_debug(cmd);
string stdout, stderr;
int status = exec_script_sync(cmd, out stdout, out stderr);
if (status == 0){
return true;
}
else{
log_error(stderr);
return false;
}
}
else{
log_error(_("File is missing") + ": %s".printf(src_file));
}
return false;
}
// hashing -----------
private string hash_md5(string path){
Checksum checksum = new Checksum (ChecksumType.MD5);
FileStream stream = FileStream.open (path, "rb");
uint8 fbuf[100];
size_t size;
while ((size = stream.read (fbuf)) > 0){
checksum.update (fbuf, size);
}
unowned string digest = checksum.get_string();
return digest;
}
// misc --------------------
public string format_file_size (
@ -799,45 +564,18 @@ namespace TeeJee.FileSystem{
}
public string escape_single_quote(string file_path){
return file_path.replace("'","'\\''");
}
// dep: chmod
public int chmod (string file, string permission){
/* Change file permissions */
string cmd = "chmod %s '%s'".printf(permission, escape_single_quote(file));
return exec_sync (cmd, null, null);
}
// dep: realpath
public string resolve_relative_path (string filePath){
/* Resolve the full path of given file using 'realpath' command */
string filePath2 = filePath;
if (filePath2.has_prefix ("~")){
filePath2 = Environment.get_home_dir () + "/" + filePath2[2:filePath2.length];
}
try {
string output = "";
string cmd = "realpath '%s'".printf(escape_single_quote(filePath2));
Process.spawn_command_line_sync(cmd, out output);
output = output.strip ();
if (FileUtils.test(output, GLib.FileTest.EXISTS)){
return output;
}
}
catch(Error e){
log_error (e.message);
}
return filePath2;
}
public int rsync (string sourceDirectory, string destDirectory, bool updateExisting, bool deleteExtra){
public int rsync(string sourceDirectory, string destDirectory, bool updateExisting, bool deleteExtra){
/* Sync files with rsync */

View File

@ -31,53 +31,6 @@ namespace TeeJee.Misc {
using TeeJee.FileSystem;
using TeeJee.ProcessHelper;
// color format -------------------
public static Gdk.RGBA hex_to_rgba (string hex_color){
/* Converts the color in hex to RGBA */
string hex = hex_color.strip().down();
if (hex.has_prefix("#") == false){
hex = "#" + hex;
}
Gdk.RGBA color = Gdk.RGBA();
if(color.parse(hex) == false){
color.parse("#000000");
}
color.alpha = 255;
return color;
}
public static string rgba_to_hex (Gdk.RGBA color, bool alpha = false, bool prefix_hash = true){
/* Converts the color in RGBA to hex */
string hex = "";
if (alpha){
hex = "%02x%02x%02x%02x".printf((uint)(Math.round(color.red*255)),
(uint)(Math.round(color.green*255)),
(uint)(Math.round(color.blue*255)),
(uint)(Math.round(color.alpha*255)))
.up();
}
else {
hex = "%02x%02x%02x".printf((uint)(Math.round(color.red*255)),
(uint)(Math.round(color.green*255)),
(uint)(Math.round(color.blue*255)))
.up();
}
if (prefix_hash){
hex = "#" + hex;
}
return hex;
}
// localization --------------------
public void set_numeric_locale(string type){
@ -105,14 +58,14 @@ namespace TeeJee.Misc {
}
}
public string timestamp_numeric (){
public string timestamp_numeric(){
/* Returns a numeric timestamp string */
return "%ld".printf((long) time_t ());
}
public string timestamp_for_path (){
public string timestamp_for_path(){
/* Returns a formatted timestamp string */

View File

@ -23,6 +23,7 @@
*/
namespace TeeJee.ProcessHelper{
using TeeJee.Logging;
using TeeJee.FileSystem;
using TeeJee.Misc;
@ -77,7 +78,7 @@ namespace TeeJee.ProcessHelper{
public int exec_script_sync (string script,
out string? std_out = null, out string? std_err = null,
bool supress_errors = false, bool run_as_admin = false,
bool supress_errors = false, bool run_as_admin = false,
bool cleanup_tmp = true, bool print_to_terminal = false){
/* Executes commands synchronously.
@ -342,35 +343,6 @@ namespace TeeJee.ProcessHelper{
return -1;
}
public void get_proc_io_stats(int pid, out int64 read_bytes, out int64 write_bytes){
/* Returns the number of bytes read and written by a process to disk */
string io_stat_file_path = "/proc/%d/io".printf(pid);
var file = File.new_for_path(io_stat_file_path);
read_bytes = 0;
write_bytes = 0;
try {
if (file.query_exists()){
var dis = new DataInputStream (file.read());
string line;
while ((line = dis.read_line (null)) != null) {
if(line.has_prefix("rchar:")){
read_bytes = int64.parse(line.replace("rchar:","").strip());
}
else if(line.has_prefix("wchar:")){
write_bytes = int64.parse(line.replace("wchar:","").strip());
}
}
} //stream closed
}
catch(Error e){
log_error (e.message);
}
}
// dep: ps TODO: Rewrite using /proc
public bool process_is_running(long pid){

View File

@ -151,7 +151,6 @@ namespace TeeJee.System{
return get_user_home(get_username_effective());
}
// application -----------------------------------------------
public string get_app_path(){
@ -286,45 +285,6 @@ namespace TeeJee.System{
// internet helpers ----------------------
public bool check_internet_connectivity(){
bool connected = false;
connected = check_internet_connectivity_test1();
if (connected){
return connected;
}
if (!connected){
connected = check_internet_connectivity_test2();
}
return connected;
}
public bool check_internet_connectivity_test1(){
int exit_code = -1;
string std_err;
string std_out;
string cmd = "ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3`\n";
cmd += "exit $?";
exit_code = exec_script_sync(cmd, out std_out, out std_err, false);
return (exit_code == 0);
}
public bool check_internet_connectivity_test2(){
int exit_code = -1;
string std_err;
string std_out;
string cmd = "ping -q -w 1 -c 1 google.com\n";
cmd += "exit $?";
exit_code = exec_script_sync(cmd, out std_out, out std_err, false);
return (exit_code == 0);
}
public bool shutdown (){
/* Shutdown the system immediately */
@ -472,43 +432,6 @@ namespace TeeJee.System{
return dir_exists("/sys/firmware/efi");
}
public void open_terminal_window(
string terminal_emulator,
string working_dir,
string script_file_to_execute,
bool run_as_admin){
string cmd = "";
if (run_as_admin){
cmd += "pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY ";
}
string term = terminal_emulator;
if (!command_exists(term)){
term = "gnome-terminal";
if (!command_exists(term)){
term = "xfce4-terminal";
}
}
cmd += term;
switch (term){
case "gnome-terminal":
case "xfce4-terminal":
if (working_dir.length > 0){
cmd += " --working-directory='%s'".printf(escape_single_quote(working_dir));
}
if (script_file_to_execute.length > 0){
cmd += " -e '%s\n; echo Press ENTER to exit... ; read dummy;'".printf(escape_single_quote(script_file_to_execute));
}
break;
}
log_debug(cmd);
exec_script_async(cmd);
}
// timers --------------------------------------------------
public GLib.Timer timer_start(){
@ -551,7 +474,6 @@ namespace TeeJee.System{
log_msg("%s %lu\n".printf(seconds.to_string(), microseconds));
}
public void set_numeric_locale(string type){
Intl.setlocale(GLib.LocaleCategory.NUMERIC, type);
Intl.setlocale(GLib.LocaleCategory.COLLATE, type);

View File

@ -5,6 +5,7 @@ CHECKEXECS := $(foreach exec,$(EXECUTABLES), $(if $(shell which $(exec)),,$(erro
prefix=/usr
sysconfdir=/etc
appconfdir=$(sysconfdir)/timeshift
bindir=$(prefix)/bin
sharedir=$(prefix)/share
polkitdir=$(sharedir)/polkit-1/actions
@ -54,7 +55,7 @@ app-gtk:
Core/*.vala Gtk/*.vala Utility/*.vala Utility/Gtk/*.vala \
-o ${app_name}-gtk \
--pkg glib-2.0 --pkg gio-unix-2.0 --pkg posix \
--pkg gee-0.8 --pkg json-glib-1.0 \
--pkg gee-0.8 --pkg json-glib-1.0 --pkg gio-2.0 \
--pkg gtk+-3.0 --pkg vte-2.91 $(xapp_pkg)
app-console:
@ -65,7 +66,7 @@ app-console:
Core/*.vala Utility/*.vala Utility/Gtk/*.vala Console/*.vala \
-o ${app_name} \
--pkg glib-2.0 --pkg gio-unix-2.0 --pkg posix \
--pkg gee-0.8 --pkg json-glib-1.0 \
--pkg gee-0.8 --pkg json-glib-1.0 --pkg gio-2.0 \
--pkg gtk+-3.0 --pkg vte-2.91 $(xapp_pkg)
manpage:
@ -102,7 +103,8 @@ install:
mkdir -p "$(DESTDIR)$(man1dir)"
mkdir -p "$(DESTDIR)$(launcherdir)"
mkdir -p "$(DESTDIR)$(polkitdir)"
mkdir -p "$(DESTDIR)$(sysconfdir)/default"
mkdir -p "$(DESTDIR)$(sysconfdir)"
mkdir -p "$(DESTDIR)$(appconfdir)"
mkdir -p "$(DESTDIR)$(sharedir)/${app_name}"
mkdir -p "$(DESTDIR)$(sharedir)/icons"
mkdir -p "$(DESTDIR)$(sharedir)/appdata"
@ -126,7 +128,7 @@ install:
install -m 0755 ${app_name}-gtk.desktop "$(DESTDIR)$(launcherdir)"
# config
install -m 0644 ../files/${app_name}.json "$(DESTDIR)$(sysconfdir)/default"
install -m 0644 ../files/${app_name}.json "$(DESTDIR)$(appconfdir)/default.json"
# man page
install -m 0644 ../man/${app_name}.1.gz "$(DESTDIR)$(man1dir)/${app_name}.1.gz"
@ -136,7 +138,7 @@ install:
chmod --recursive 0644 $(DESTDIR)$(sharedir)/icons/hicolor/*/apps/${app_name}.png
# appdata
install -m 0644 ../debian/${app_name}.appdata.xml "$(DESTDIR)$(sharedir)/appdata"
#install -m 0644 ../debian/${app_name}.appdata.xml "$(DESTDIR)$(sharedir)/appdata"
install -m 0644 ../debian/${app_name}.appdata.xml "$(DESTDIR)$(sharedir)/metainfo"
# translations

View File

@ -2,23 +2,23 @@
app_command='timeshift-gtk'
if [ `id -u` -eq 0 ]; then
#user is admin
if [ "$(id -u)" -eq 0 ]; then
# user is admin
${app_command}
else
#user is not admin
if `echo $- | grep "i" >/dev/null 2>&1`; then
#script is running in interactive mode
# user is not admin
if echo $- | grep "i" >/dev/null 2>&1; then
# script is running in interactive mode
su - -c "${app_command}"
else
#script is running in non-interactive mode
if [ $XDG_SESSION_TYPE = "wayland" ] ; then
# script is running in non-interactive mode
if [ "$XDG_SESSION_TYPE" = "wayland" ] ; then
xhost +SI:localuser:root
pkexec ${app_command}
xhost -SI:localuser:root
xhost
elif command -v pkexec >/dev/null 2>&1; then
pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY ${app_command}
pkexec ${app_command}
elif command -v sudo >/dev/null 2>&1; then
x-terminal-emulator -e "sudo ${app_command}"
elif command -v su >/dev/null 2>&1; then

1
timeshift-wiki Submodule

@ -0,0 +1 @@
Subproject commit aa75c12bc38fc77a62d1002d7d442b4f102ab436

View File

@ -1,132 +0,0 @@
[indentation]
indent_width=4
indent_type=1
indent_hard_tab_width=8
detect_indent=false
detect_indent_width=false
indent_mode=2
[project]
name=timeshift
base_path=/home/teejee/projects/linux/timeshift
description=
file_patterns=
[long line marker]
long_line_behaviour=1
long_line_column=80
[files]
current_page=44
FILE_NAME_0=26;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FArchiveFile.vala;0;4
FILE_NAME_1=24;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FAsyncTask.vala;0;4
FILE_NAME_2=19;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FBash.vala;0;4
FILE_NAME_3=22;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FCronTab.vala;0;4
FILE_NAME_4=23;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FFileItem.vala;0;4
FILE_NAME_5=25;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FLinuxDistro.vala;0;4
FILE_NAME_6=25;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FOSDNotify.vala;0;4
FILE_NAME_7=25;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FProcStats.vala;0;4
FILE_NAME_8=7528;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.FileSystem.vala;0;4
FILE_NAME_9=33;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.Json.vala;0;4
FILE_NAME_10=30;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.Logging.vala;0;4
FILE_NAME_11=1329;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.Misc.vala;0;4
FILE_NAME_12=3234;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.Process.vala;0;4
FILE_NAME_13=8888;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTeeJee.System.vala;0;4
FILE_NAME_14=2726;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FExcludeMessageWindow.vala;0;4
FILE_NAME_15=2073;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FMainWindow.vala;0;4
FILE_NAME_16=4051;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreWindow.vala;0;4
FILE_NAME_17=2406;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FSettingsWindow.vala;0;4
FILE_NAME_18=24;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FRsyncTask.vala;0;4
FILE_NAME_19=27;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FCore%2FAppExcludeEntry.vala;0;4
FILE_NAME_20=8401;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FCore%2FSnapshot.vala;0;4
FILE_NAME_21=5234;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FCore%2FSnapshotRepo.vala;0;4
FILE_NAME_22=2001;Make;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2Fmakefile;0;4
FILE_NAME_23=29;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRsyncLogWindow.vala;0;4
FILE_NAME_24=3540;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FBackupBox.vala;0;4
FILE_NAME_25=26;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FEstimateBox.vala;0;4
FILE_NAME_26=10217;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FBackupDeviceBox.vala;0;4
FILE_NAME_27=6002;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FExcludeBox.vala;0;4
FILE_NAME_28=7388;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FScheduleBox.vala;0;4
FILE_NAME_29=2532;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FFinishBox.vala;0;4
FILE_NAME_30=4344;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FSetupWizardWindow.vala;0;4
FILE_NAME_31=2801;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FBackupWindow.vala;0;4
FILE_NAME_32=1011;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FSnapshotListBox.vala;0;4
FILE_NAME_33=1402;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FDeleteWindow.vala;0;4
FILE_NAME_34=0;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FDeleteBox.vala;0;4
FILE_NAME_35=29;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FDeleteFileTask.vala;0;4
FILE_NAME_36=2025;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreBox.vala;0;4
FILE_NAME_37=1972;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreSummaryBox.vala;0;4
FILE_NAME_38=4010;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreDeviceBox.vala;0;4
FILE_NAME_39=0;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreExcludeBox.vala;0;4
FILE_NAME_40=2324;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRestoreFinishBox.vala;0;4
FILE_NAME_41=1712;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FExcludeAppsBox.vala;0;4
FILE_NAME_42=39;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FExcludeListSummaryWindow.vala;0;4
FILE_NAME_43=41629;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FDevice.vala;0;4
FILE_NAME_44=438;None;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fdebian%2Fchangelog;0;4
FILE_NAME_45=852;Conf;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fdebian%2Fcontrol;0;4
FILE_NAME_46=0;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FAppLock.vala;0;4
FILE_NAME_47=30;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FTimeoutCounter.vala;0;4
FILE_NAME_48=1441;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FAppGtk.vala;0;4
FILE_NAME_49=17372;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FConsole%2FAppConsole.vala;0;4
FILE_NAME_50=3478;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FGtk%2FTerminalWindow.vala;0;4
FILE_NAME_51=2742;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FCore%2FMain.vala;0;4
FILE_NAME_52=992;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FBootOptionsWindow.vala;0;4
FILE_NAME_53=0;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FBootOptionsBox.vala;0;4
FILE_NAME_54=19269;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FGtkHelper.vala;0;4
FILE_NAME_55=1669;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FCore%2FSubvolume.vala;0;4
FILE_NAME_56=1074;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FDeleteFinishBox.vala;0;4
FILE_NAME_57=3943;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FSnapshotBackendBox.vala;0;4
FILE_NAME_58=10039;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FGtk%2FAboutWindow.vala;0;4
FILE_NAME_59=34;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FGtk%2FCustomMessageDialog.vala;0;4
FILE_NAME_60=2710;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FFsTabEntry.vala;0;4
FILE_NAME_61=27;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FSystemGroup.vala;0;4
FILE_NAME_62=895;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FSystemUser.vala;0;4
FILE_NAME_63=7678;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FUsersBox.vala;0;4
FILE_NAME_64=548;JSON;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Ffiles%2Ftimeshift.json;0;4
FILE_NAME_65=697;Conf;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2Ftimeshift-gtk.desktop;0;4
FILE_NAME_66=3473;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FGtk%2FDonationWindow.vala;0;4
FILE_NAME_67=2818;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FIconManager.vala;0;4
FILE_NAME_68=0;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FLicenseText.vala;0;4
FILE_NAME_69=702;Sh;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fbuild-installers.sh;0;4
FILE_NAME_70=11903;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FGtk%2FRsyncLogBox.vala;0;4
FILE_NAME_71=46967;Po;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fpo%2Ftimeshift-sv.po;0;4
FILE_NAME_72=1064;Sh;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fmerge-launchpad-translations.sh;0;4
FILE_NAME_73=780;Vala;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2FUtility%2FMountEntry.vala;0;4
FILE_NAME_74=279;None;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Frelease%2Fsanity.config;0;4
FILE_NAME_75=528;Sh;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fsrc%2Ftimeshift-launcher;0;4
FILE_NAME_76=120;Make;0;EUTF-8;1;1;1;%2Fhome%2Fteejee%2Fprojects%2Flinux%2Ftimeshift%2Fmakefile;0;4
[VTE]
last_dir=/data/projects/linux/timeshift
[build-menu]
ValaFT_00_LB=_Compile
ValaFT_00_CM=
ValaFT_00_WD=
filetypes=Vala;Make;
NF_00_LB=_Make
NF_00_CM=make app-console app-gtk
NF_00_WD=%p
EX_00_LB=_Execute Debug
EX_00_CM=pkexec timeshift-gtk
EX_00_WD=%p/src
EX_01_LB=Execute
EX_01_CM=pkexec timeshift-gtk
EX_01_WD=%p/src
ValaFT_01_LB=_Build
ValaFT_01_CM=make app-console app-gtk
ValaFT_01_WD=%p
MakeFT_00_LB=
MakeFT_00_CM=make app-console app-gtk
MakeFT_00_WD=%p
[file_prefs]
final_new_line=true
ensure_convert_new_lines=false
strip_trailing_spaces=false
replace_tabs=false
[editor]
line_wrapping=true
line_break_column=72
auto_continue_multiline=true

File diff suppressed because it is too large Load Diff