~teejee2008/timeshift/trunk

« back to all changes in this revision

Viewing changes to src/Utility/TeeJee.FileSystem.vala

  • Committer: Tony George
  • Date: 2016-08-13 04:16:47 UTC
  • Revision ID: tony.george.kol@gmail.com-20160813041647-ivf2g6rszt00xco5
Updated project structure

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * TeeJee.FileSystem.vala
 
4
 *
 
5
 * Copyright 2016 Tony George <teejee2008@gmail.com>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
20
 * MA 02110-1301, USA.
 
21
 *
 
22
 *
 
23
 */
 
24
 
 
25
namespace TeeJee.FileSystem{
 
26
 
 
27
        /* Convenience functions for handling files and directories */
 
28
 
 
29
        using TeeJee.Logging;
 
30
        using TeeJee.ProcessHelper;
 
31
        using TeeJee.Misc;
 
32
 
 
33
 
 
34
        public const int64 KB = 1000;
 
35
        public const int64 MB = 1000 * KB;
 
36
        public const int64 GB = 1000 * MB;
 
37
        public const int64 TB = 1000 * GB;
 
38
        public const int64 KiB = 1024;
 
39
        public const int64 MiB = 1024 * KiB;
 
40
        public const int64 GiB = 1024 * MiB;
 
41
        public const int64 TiB = 1024 * GiB;
 
42
        
 
43
        // path helpers ----------------------------
 
44
        
 
45
        public string file_parent(string file_path){
 
46
                return File.new_for_path(file_path).get_parent().get_path();
 
47
        }
 
48
 
 
49
        public string file_basename(string file_path){
 
50
                return File.new_for_path(file_path).get_basename();
 
51
        }
 
52
 
 
53
        public string path_combine(string path1, string path2){
 
54
                return GLib.Path.build_path("/", path1, path2);
 
55
        }
 
56
        
 
57
        // file helpers -----------------------------
 
58
 
 
59
        public bool file_or_dir_exists(string item_path){
 
60
                
 
61
                /* check if item exists on disk*/
 
62
 
 
63
                try{
 
64
                        var item = File.parse_name(item_path);
 
65
                        return item.query_exists();
 
66
                }
 
67
                catch (Error e) {
 
68
                        log_error (e.message);
 
69
                        return false;
 
70
                }
 
71
        }
 
72
        
 
73
        public bool file_exists (string file_path){
 
74
                /* Check if file exists */
 
75
                return (FileUtils.test(file_path, GLib.FileTest.EXISTS)
 
76
                && !FileUtils.test(file_path, GLib.FileTest.IS_DIR));
 
77
        }
 
78
 
 
79
        public bool file_exists_regular (string file_path){
 
80
                /* Check if file exists */
 
81
                return ( FileUtils.test(file_path, GLib.FileTest.EXISTS)
 
82
                && FileUtils.test(file_path, GLib.FileTest.IS_REGULAR));
 
83
        }
 
84
 
 
85
        public bool file_delete(string file_path){
 
86
 
 
87
                /* Check and delete file */
 
88
 
 
89
                try {
 
90
                        var file = File.new_for_path (file_path);
 
91
                        if (file.query_exists ()) {
 
92
                                file.delete ();
 
93
                        }
 
94
                        return true;
 
95
                } catch (Error e) {
 
96
                log_error (e.message);
 
97
                log_error(_("Failed to delete file") + ": %s".printf(file_path));
 
98
                return false;
 
99
            }
 
100
        }
 
101
 
 
102
        public bool file_move_to_trash(string file_path){
 
103
 
 
104
                /* Check and delete file */
 
105
 
 
106
                var file = File.new_for_path (file_path);
 
107
                if (file.query_exists ()) {
 
108
                        Posix.system("gvfs-trash '%s'".printf(escape_single_quote(file_path)));
 
109
                }
 
110
                return true;
 
111
        }
 
112
 
 
113
        public bool file_shred(string file_path){
 
114
 
 
115
                /* Check and delete file */
 
116
 
 
117
                try {
 
118
                        var file = File.new_for_path (file_path);
 
119
                        if (file.query_exists ()) {
 
120
                                Posix.system("shred -u '%s'".printf(escape_single_quote(file_path)));
 
121
                        }
 
122
                        return true;
 
123
                }
 
124
                catch (Error e) {
 
125
                log_error (e.message);
 
126
                log_error(_("Failed to delete file") + ": %s".printf(file_path));
 
127
                return false;
 
128
            }
 
129
        }
 
130
 
 
131
 
 
132
        public string? file_read (string file_path){
 
133
 
 
134
                /* Reads text from file */
 
135
 
 
136
                string txt;
 
137
                size_t size;
 
138
 
 
139
                try{
 
140
                        GLib.FileUtils.get_contents (file_path, out txt, out size);
 
141
                        return txt;
 
142
                }
 
143
                catch (Error e){
 
144
                log_error (e.message);
 
145
                log_error(_("Failed to read file") + ": %s".printf(file_path));
 
146
            }
 
147
 
 
148
            return null;
 
149
        }
 
150
 
 
151
        public bool file_write (string file_path, string contents){
 
152
 
 
153
                /* Write text to file */
 
154
 
 
155
                try{
 
156
 
 
157
                        dir_create(file_parent(file_path));
 
158
                        
 
159
                        var file = File.new_for_path (file_path);
 
160
                        if (file.query_exists ()) {
 
161
                                file.delete ();
 
162
                        }
 
163
                        
 
164
                        var file_stream = file.create (FileCreateFlags.REPLACE_DESTINATION);
 
165
                        var data_stream = new DataOutputStream (file_stream);
 
166
                        data_stream.put_string (contents);
 
167
                        data_stream.close();
 
168
                        return true;
 
169
                }
 
170
                catch (Error e) {
 
171
                        log_error (e.message);
 
172
                        log_error(_("Failed to write file") + ": %s".printf(file_path));
 
173
                        return false;
 
174
                }
 
175
        }
 
176
 
 
177
        public bool file_copy (string src_file, string dest_file){
 
178
                try{
 
179
                        var file_src = File.new_for_path (src_file);
 
180
                        if (file_src.query_exists()) {
 
181
                                var file_dest = File.new_for_path (dest_file);
 
182
                                file_src.copy(file_dest,FileCopyFlags.OVERWRITE,null,null);
 
183
                                return true;
 
184
                        }
 
185
                }
 
186
                catch(Error e){
 
187
                log_error (e.message);
 
188
                log_error(_("Failed to copy file") + ": '%s', '%s'".printf(src_file, dest_file));
 
189
                }
 
190
 
 
191
                return false;
 
192
        }
 
193
 
 
194
        public void file_move (string src_file, string dest_file){
 
195
                try{
 
196
                        var file_src = File.new_for_path (src_file);
 
197
                        if (file_src.query_exists()) {
 
198
                                var file_dest = File.new_for_path (dest_file);
 
199
                                file_src.move(file_dest,FileCopyFlags.OVERWRITE,null,null);
 
200
                        }
 
201
                        else{
 
202
                                log_error(_("File not found") + ": '%s'".printf(src_file));
 
203
                        }
 
204
                }
 
205
                catch(Error e){
 
206
                log_error (e.message);
 
207
                log_error(_("Failed to move file") + ": '%s', '%s'".printf(src_file, dest_file));
 
208
                }
 
209
        }
 
210
 
 
211
        
 
212
        // file info -----------------
 
213
 
 
214
        public int64 file_get_size(string file_path){
 
215
                try{
 
216
                        File file = File.parse_name (file_path);
 
217
                        if (FileUtils.test(file_path, GLib.FileTest.EXISTS)){
 
218
                                if (FileUtils.test(file_path, GLib.FileTest.IS_REGULAR)
 
219
                                        && !FileUtils.test(file_path, GLib.FileTest.IS_SYMLINK)){
 
220
                                        return file.query_info("standard::size",0).get_size();
 
221
                                }
 
222
                        }
 
223
                }
 
224
                catch(Error e){
 
225
                        log_error (e.message);
 
226
                }
 
227
 
 
228
                return -1;
 
229
        }
 
230
 
 
231
        public DateTime file_get_modified_date(string file_path){
 
232
                try{
 
233
                        FileInfo info;
 
234
                        File file = File.parse_name (file_path);
 
235
                        if (file.query_exists()) {
 
236
                                info = file.query_info("%s".printf(FileAttribute.TIME_MODIFIED), 0);
 
237
                                return (new DateTime.from_timeval_utc(info.get_modification_time())).to_local();
 
238
                        }
 
239
                }
 
240
                catch (Error e) {
 
241
                        log_error (e.message);
 
242
                }
 
243
                
 
244
                return (new DateTime.from_unix_utc(0)); //1970
 
245
        }
 
246
        
 
247
        public string file_get_symlink_target(string file_path){
 
248
                try{
 
249
                        FileInfo info;
 
250
                        File file = File.parse_name (file_path);
 
251
                        if (file.query_exists()) {
 
252
                                info = file.query_info("%s".printf(FileAttribute.STANDARD_SYMLINK_TARGET), 0);
 
253
                                return info.get_symlink_target();
 
254
                        }
 
255
                }
 
256
                catch (Error e) {
 
257
                        log_error (e.message);
 
258
                }
 
259
                
 
260
                return "";
 
261
        }
 
262
 
 
263
        // directory helpers ----------------------
 
264
        
 
265
        public bool dir_exists (string dir_path){
 
266
                /* Check if directory exists */
 
267
                return ( FileUtils.test(dir_path, GLib.FileTest.EXISTS) && FileUtils.test(dir_path, GLib.FileTest.IS_DIR));
 
268
        }
 
269
        
 
270
        public bool dir_create (string dir_path){
 
271
 
 
272
                /* Creates a directory along with parents */
 
273
 
 
274
                try{
 
275
                        var dir = File.parse_name (dir_path);
 
276
                        if (dir.query_exists () == false) {
 
277
                                dir.make_directory_with_parents (null);
 
278
                        }
 
279
                        return true;
 
280
                }
 
281
                catch (Error e) {
 
282
                        log_error (e.message);
 
283
                        log_error(_("Failed to create dir") + ": %s".printf(dir_path));
 
284
                        return false;
 
285
                }
 
286
        }
 
287
 
 
288
        public bool dir_delete (string dir_path){
 
289
                
 
290
                /* Recursively deletes directory along with contents */
 
291
                
 
292
                string cmd = "rm -rf '%s'".printf(escape_single_quote(dir_path));
 
293
                int status = exec_sync(cmd);
 
294
                return (status == 0);
 
295
        }
 
296
 
 
297
        public bool dir_move_to_trash (string dir_path){
 
298
                return file_move_to_trash(dir_path);
 
299
        }
 
300
        
 
301
        public bool dir_is_empty (string dir_path){
 
302
 
 
303
                /* Check if directory is empty */
 
304
 
 
305
                try{
 
306
                        bool is_empty = true;
 
307
                        var dir = File.parse_name (dir_path);
 
308
                        if (dir.query_exists()) {
 
309
                                FileInfo info;
 
310
                                var enu = dir.enumerate_children ("%s".printf(FileAttribute.STANDARD_NAME), 0);
 
311
                                while ((info = enu.next_file()) != null) {
 
312
                                        is_empty = false;
 
313
                                        break;
 
314
                                }
 
315
                        }
 
316
                        return is_empty;
 
317
                }
 
318
                catch (Error e) {
 
319
                        log_error (e.message);
 
320
                        return false;
 
321
                }
 
322
        }
 
323
 
 
324
 
 
325
        public Gee.ArrayList<string> dir_list_names(string path){
 
326
                var list = new Gee.ArrayList<string>();
 
327
                
 
328
                try
 
329
                {
 
330
                        File f_home = File.new_for_path (path);
 
331
                        FileEnumerator enumerator = f_home.enumerate_children ("%s".printf(FileAttribute.STANDARD_NAME), 0);
 
332
                        FileInfo file;
 
333
                        while ((file = enumerator.next_file ()) != null) {
 
334
                                string name = file.get_name();
 
335
                                list.add(name);
 
336
                        }
 
337
                }
 
338
                catch (Error e) {
 
339
                        log_error (e.message);
 
340
                }
 
341
 
 
342
                //sort the list
 
343
                CompareDataFunc<string> entry_compare = (a, b) => {
 
344
                        return strcmp(a,b);
 
345
                };
 
346
                list.sort((owned) entry_compare);
 
347
 
 
348
                return list;
 
349
        }
 
350
        
 
351
        public bool dir_tar (string src_dir, string tar_file, bool recursion = true){
 
352
                if (dir_exists(src_dir)) {
 
353
                        
 
354
                        if (file_exists(tar_file)){
 
355
                                file_delete(tar_file);
 
356
                        }
 
357
 
 
358
                        var src_parent = file_parent(src_dir);
 
359
                        var src_name = file_basename(src_dir);
 
360
                        
 
361
                        string cmd = "tar cvf '%s' --overwrite --%srecursion -C '%s' '%s'\n".printf(
 
362
                                escape_single_quote(tar_file),
 
363
                                (recursion ? "" : "no-"),
 
364
                                escape_single_quote(src_parent),
 
365
                                escape_single_quote(src_name));
 
366
 
 
367
                        log_debug(cmd);
 
368
                        
 
369
                        string stdout, stderr;
 
370
                        int status = exec_script_sync(cmd, out stdout, out stderr);
 
371
                        if (status == 0){
 
372
                                return true;
 
373
                        }
 
374
                        else{
 
375
                                log_msg(stderr);
 
376
                        }
 
377
                }
 
378
                else{
 
379
                        log_error(_("Dir not found") + ": %s".printf(src_dir));
 
380
                }
 
381
 
 
382
                return false;
 
383
        }
 
384
 
 
385
        public bool dir_untar (string tar_file, string dst_dir){
 
386
                if (file_exists(tar_file)) {
 
387
 
 
388
                        if (!dir_exists(dst_dir)){
 
389
                                dir_create(dst_dir);
 
390
                        }
 
391
                        
 
392
                        string cmd = "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(
 
393
                                escape_single_quote(tar_file),
 
394
                                escape_single_quote(dst_dir));
 
395
 
 
396
                        log_debug(cmd);
 
397
                        
 
398
                        string stdout, stderr;
 
399
                        int status = exec_script_sync(cmd, out stdout, out stderr);
 
400
                        if (status == 0){
 
401
                                return true;
 
402
                        }
 
403
                        else{
 
404
                                log_msg(stderr);
 
405
                        }
 
406
                }
 
407
                else{
 
408
                        log_error(_("File not found") + ": %s".printf(tar_file));
 
409
                }
 
410
                
 
411
                return false;
 
412
        }
 
413
 
 
414
        public bool chown(string dir_path, string user, string group = user){
 
415
                string cmd = "chown %s:%s -R '%s'".printf(user, group, escape_single_quote(dir_path));
 
416
                int status = exec_sync(cmd, null, null);
 
417
                return (status == 0);
 
418
        }
 
419
        
 
420
        // dir info -------------------
 
421
        
 
422
        // dep: find wc    TODO: rewrite
 
423
        public long dir_count(string path){
 
424
 
 
425
                /* Return total count of files and directories */
 
426
 
 
427
                string cmd = "";
 
428
                string std_out;
 
429
                string std_err;
 
430
                int ret_val;
 
431
 
 
432
                cmd = "find '%s' | wc -l".printf(escape_single_quote(path));
 
433
                ret_val = exec_script_sync(cmd, out std_out, out std_err);
 
434
                return long.parse(std_out);
 
435
        }
 
436
 
 
437
        // dep: du
 
438
        public long dir_size(string path){
 
439
 
 
440
                /* Returns size of files and directories in KB*/
 
441
 
 
442
                string cmd = "du -s -b '%s'".printf(escape_single_quote(path));
 
443
                string std_out, std_err;
 
444
                exec_sync(cmd, out std_out, out std_err);
 
445
                return long.parse(std_out.split("\t")[0]);
 
446
        }
 
447
 
 
448
        // dep: du
 
449
        public long dir_size_kb(string path){
 
450
 
 
451
                /* Returns size of files and directories in KB*/
 
452
 
 
453
                return (long)(dir_size(path) / 1024.0);
 
454
        }
 
455
 
 
456
        // archiving and encryption ----------------
 
457
 
 
458
        // dep: tar gzip gpg
 
459
        public bool file_tar_encrypt (string src_file, string dst_file, string password){
 
460
                if (file_exists(src_file)) {
 
461
                        if (file_exists(dst_file)){
 
462
                                file_delete(dst_file);
 
463
                        }
 
464
 
 
465
                        var src_dir = file_parent(src_file);
 
466
                        var src_name = file_basename(src_file);
 
467
 
 
468
                        var dst_dir = file_parent(dst_file);
 
469
                        var dst_name = file_basename(dst_file);
 
470
                        var tar_name = dst_name[0 : dst_name.index_of(".gpg")];
 
471
                        var tar_file = "%s/%s".printf(dst_dir, tar_name);
 
472
                        
 
473
                        string cmd = "tar cvf '%s' --overwrite -C '%s' '%s'\n".printf(
 
474
                                escape_single_quote(tar_file),
 
475
                                escape_single_quote(src_dir),
 
476
                                escape_single_quote(src_name));
 
477
                                
 
478
                        cmd += "gpg --passphrase '%s' -o '%s' --symmetric '%s'\n".printf(
 
479
                                password,
 
480
                                escape_single_quote(dst_file),
 
481
                                escape_single_quote(tar_file));
 
482
                                
 
483
                        cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
 
484
 
 
485
                        log_debug(cmd);
 
486
                        
 
487
                        string stdout, stderr;
 
488
                        int status = exec_script_sync(cmd, out stdout, out stderr);
 
489
                        if (status == 0){
 
490
                                return true;
 
491
                        }
 
492
                        else{
 
493
                                log_msg(stderr);
 
494
                        }
 
495
                }
 
496
 
 
497
                return false;
 
498
        }
 
499
 
 
500
        // dep: tar gzip gpg
 
501
        public string file_decrypt_untar_read (string src_file, string password){
 
502
                
 
503
                if (file_exists(src_file)) {
 
504
                        
 
505
                        //var src_name = file_basename(src_file);
 
506
                        //var tar_name = src_name[0 : src_name.index_of(".gpg")];
 
507
                        //var tar_file = "%s/%s".printf(TEMP_DIR, tar_name);
 
508
                        //var temp_file = "%s/%s".printf(TEMP_DIR, random_string());
 
509
 
 
510
                        string cmd = "";
 
511
                        
 
512
                        cmd += "gpg --quiet --no-verbose --passphrase '%s' -o- --decrypt '%s'".printf(
 
513
                                password,
 
514
                                escape_single_quote(src_file));
 
515
                                
 
516
                        cmd += " | tar xf - --to-stdout 2>/dev/null\n";
 
517
                        cmd += "exit $?\n";
 
518
                        
 
519
                        log_debug(cmd);
 
520
                        
 
521
                        string std_out, std_err;
 
522
                        int status = exec_script_sync(cmd, out std_out, out std_err);
 
523
                        if (status == 0){
 
524
                                return std_out;
 
525
                        }
 
526
                        else{
 
527
                                log_error(std_err);
 
528
                                return "";
 
529
                        }
 
530
                }
 
531
                else{
 
532
                        log_error(_("File is missing") + ": %s".printf(src_file));
 
533
                }
 
534
 
 
535
                return "";
 
536
        }
 
537
 
 
538
        // dep: tar gzip gpg
 
539
        public bool decrypt_and_untar (string src_file, string dst_file, string password){
 
540
                if (file_exists(src_file)) {
 
541
                        if (file_exists(dst_file)){
 
542
                                file_delete(dst_file);
 
543
                        }
 
544
 
 
545
                        var src_dir = file_parent(src_file);
 
546
                        var src_name = file_basename(src_file);
 
547
                        var tar_name = src_name[0 : src_name.index_of(".gpg")];
 
548
                        var tar_file = "%s/%s".printf(src_dir, tar_name);
 
549
 
 
550
                        string cmd = "";
 
551
                        
 
552
                        // gpg cannot overwrite - remove tar file if it exists
 
553
                        cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
 
554
                        
 
555
                        cmd += "gpg --passphrase '%s' -o '%s' --decrypt '%s'\n".printf(
 
556
                                password,
 
557
                                escape_single_quote(tar_file),
 
558
                                escape_single_quote(src_file));
 
559
                                
 
560
                        cmd += "status=$?; if [ $status -ne 0 ]; then exit $status; fi\n";
 
561
                        
 
562
                        cmd += "tar xvf '%s' --overwrite --same-permissions -C '%s'\n".printf(
 
563
                                escape_single_quote(tar_file),
 
564
                                escape_single_quote(file_parent(dst_file)));
 
565
                                
 
566
                        cmd += "rm -f '%s'\n".printf(escape_single_quote(tar_file));
 
567
 
 
568
                        log_debug(cmd);
 
569
                        
 
570
                        string stdout, stderr;
 
571
                        int status = exec_script_sync(cmd, out stdout, out stderr);
 
572
                        if (status == 0){
 
573
                                return true;
 
574
                        }
 
575
                        else{
 
576
                                log_error(stderr);
 
577
                                return false;
 
578
                        }
 
579
                }
 
580
                else{
 
581
                        log_error(_("File is missing") + ": %s".printf(src_file));
 
582
                }
 
583
 
 
584
                return false;
 
585
        }
 
586
 
 
587
        // hashing -----------
 
588
        
 
589
        private string hash_md5(string path){
 
590
                Checksum checksum = new Checksum (ChecksumType.MD5);
 
591
                FileStream stream = FileStream.open (path, "rb");
 
592
 
 
593
                uint8 fbuf[100];
 
594
                size_t size;
 
595
                while ((size = stream.read (fbuf)) > 0){
 
596
                  checksum.update (fbuf, size);
 
597
                }
 
598
                
 
599
                unowned string digest = checksum.get_string();
 
600
 
 
601
                return digest;
 
602
        }
 
603
 
 
604
        // misc --------------------
 
605
 
 
606
        public string format_file_size (
 
607
                uint64 size, bool binary_units = false, bool size_kb = false){
 
608
                        
 
609
                int64 unit_k = binary_units ? 1024 : 1000;
 
610
                int64 unit_m = binary_units ? 1024 * unit_k : 1000 * unit_k;
 
611
                int64 unit_g = binary_units ? 1024 * unit_m : 1000 * unit_m;
 
612
 
 
613
                if (size_kb){
 
614
                        return "%'0.0f %sB".printf(size/(1.0 * unit_k), (binary_units)?"Ki":"K");
 
615
                }
 
616
                
 
617
                if (size > unit_g){
 
618
                        return "%'0.1f %sB".printf(size/(1.0 * unit_g), (binary_units)?"Gi":"G");
 
619
                }
 
620
                else if (size > unit_m){
 
621
                        return "%'0.1f %sB".printf(size/(1.0 * unit_m), (binary_units)?"Mi":"M");
 
622
                }
 
623
                else if (size > unit_k){
 
624
                        return "%'0.0f %sB".printf(size/(1.0 * unit_k), (binary_units)?"Ki":"K");
 
625
                }
 
626
                else{
 
627
                        return "%'0lld B".printf(size);
 
628
                }
 
629
        }
 
630
 
 
631
        public string escape_single_quote(string file_path){
 
632
                return file_path.replace("'","'\\''");
 
633
        }
 
634
 
 
635
 
 
636
        // dep: chmod
 
637
        public int chmod (string file, string permission){
 
638
 
 
639
                /* Change file permissions */
 
640
                string cmd = "chmod %s '%s'".printf(permission, escape_single_quote(file));
 
641
                return exec_sync (cmd, null, null);
 
642
        }
 
643
 
 
644
        // dep: realpath
 
645
        public string resolve_relative_path (string filePath){
 
646
 
 
647
                /* Resolve the full path of given file using 'realpath' command */
 
648
 
 
649
                string filePath2 = filePath;
 
650
                if (filePath2.has_prefix ("~")){
 
651
                        filePath2 = Environment.get_home_dir () + "/" + filePath2[2:filePath2.length];
 
652
                }
 
653
 
 
654
                try {
 
655
                        string output = "";
 
656
                        string cmd = "realpath '%s'".printf(escape_single_quote(filePath2));
 
657
                        Process.spawn_command_line_sync(cmd, out output);
 
658
                        output = output.strip ();
 
659
                        if (FileUtils.test(output, GLib.FileTest.EXISTS)){
 
660
                                return output;
 
661
                        }
 
662
                }
 
663
                catch(Error e){
 
664
                log_error (e.message);
 
665
            }
 
666
 
 
667
            return filePath2;
 
668
        }
 
669
 
 
670
        public int rsync (string sourceDirectory, string destDirectory, bool updateExisting, bool deleteExtra){
 
671
 
 
672
                /* Sync files with rsync */
 
673
 
 
674
                string cmd = "rsync -avh";
 
675
                cmd += updateExisting ? "" : " --ignore-existing";
 
676
                cmd += deleteExtra ? " --delete" : "";
 
677
                cmd += " '%s'".printf(escape_single_quote(sourceDirectory) + "//");
 
678
                cmd += " '%s'".printf(escape_single_quote(destDirectory));
 
679
                return exec_sync (cmd, null, null);
 
680
        }
 
681
}