evolution-3.6.4/modules/backup-restore/evolution-backup-tool.c

Location Tool Test ID Function Issue
evolution-backup-tool.c:267:4 gcc unused-result run_cmd ignoring return value of 'system', declared with attribute warn_unused_result
evolution-backup-tool.c:271:3 gcc unused-result run_cmd ignoring return value of 'system', declared with attribute warn_unused_result
   1 /*
   2  * evolution-backup-tool.c
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) version 3.
   8  *
   9  * This program is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * Lesser General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  16  *
  17  */
  18 
  19 #ifdef HAVE_CONFIG_H
  20 #include <config.h>
  21 #endif
  22 
  23 #include <errno.h>
  24 #include <stdio.h>
  25 #include <stdlib.h>
  26 #include <string.h>
  27 
  28 #include <glib/gi18n.h>
  29 #include <glib/gstdio.h>
  30 #include <gtk/gtk.h>
  31 
  32 #include <libedataserver/libedataserver.h>
  33 
  34 #ifdef G_OS_WIN32
  35 #ifdef DATADIR
  36 #undef DATADIR
  37 #endif
  38 #include <windows.h>
  39 #include <conio.h>
  40 #ifndef PROCESS_DEP_ENABLE
  41 #define PROCESS_DEP_ENABLE 0x00000001
  42 #endif
  43 #ifndef PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION
  44 #define PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION 0x00000002
  45 #endif
  46 #endif
  47 
  48 #include "e-util/e-util-private.h"
  49 #include "e-util/e-util.h"
  50 
  51 #define EVOUSERDATADIR_MAGIC "#EVO_USERDATADIR#"
  52 
  53 #define EVOLUTION "evolution"
  54 #define EVOLUTION_DIR "$DATADIR/"
  55 #define EVOLUTION_DIR_FILE EVOLUTION ".dir"
  56 #define DBUS_SOURCE_REGISTRY_SERVICE_FILE "$DBUSDATADIR/org.gnome.evolution.dataserver.Sources.service"
  57 
  58 #define ANCIENT_GCONF_DUMP_FILE "backup-restore-gconf.xml"
  59 
  60 #define DCONF_DUMP_FILE_EDS "backup-restore-dconf-eds.ini"
  61 #define DCONF_DUMP_FILE_EVO "backup-restore-dconf-evo.ini"
  62 
  63 #define DCONF_PATH_EDS "/org/gnome/evolution-data-server/"
  64 #define DCONF_PATH_EVO "/org/gnome/evolution/"
  65 
  66 #define KEY_FILE_GROUP "Evolution Backup"
  67 
  68 static gboolean backup_op = FALSE;
  69 static gchar *bk_file = NULL;
  70 static gboolean restore_op = FALSE;
  71 static gchar *res_file = NULL;
  72 static gboolean check_op = FALSE;
  73 static gchar *chk_file = NULL;
  74 static gboolean restart_arg = FALSE;
  75 static gboolean gui_arg = FALSE;
  76 static gchar **opt_remaining = NULL;
  77 static gint result = 0;
  78 static GtkWidget *progress_dialog;
  79 static GtkWidget *pbar;
  80 static gchar *txt = NULL;
  81 
  82 static GOptionEntry options[] = {
  83 	{ "backup", '\0', 0, G_OPTION_ARG_NONE, &backup_op,
  84 	  N_("Back up Evolution directory"), NULL },
  85 	{ "restore", '\0', 0, G_OPTION_ARG_NONE, &restore_op,
  86 	  N_("Restore Evolution directory"), NULL },
  87 	{ "check", '\0', 0, G_OPTION_ARG_NONE, &check_op,
  88 	  N_("Check Evolution Back up"), NULL },
  89 	{ "restart", '\0', 0, G_OPTION_ARG_NONE, &restart_arg,
  90 	  N_("Restart Evolution"), NULL },
  91 	{ "gui", '\0', 0, G_OPTION_ARG_NONE, &gui_arg,
  92 	  N_("With Graphical User Interface"), NULL },
  93 	{ G_OPTION_REMAINING, '\0', 0,
  94 	  G_OPTION_ARG_STRING_ARRAY, &opt_remaining },
  95 	{ NULL }
  96 };
  97 
  98 #define d(x)
  99 
 100 #define print_and_run(x) \
 101 	G_STMT_START { g_message ("%s", x); system (x); } G_STMT_END
 102 
 103 static gboolean check (const gchar *filename, gboolean *is_new_format);
 104 
 105 static GString *
 106 replace_string (const gchar *text,
 107                 const gchar *find,
 108                 const gchar *replace)
 109 {
 110 	const gchar *p, *next;
 111 	GString *str;
 112 	gint find_len;
 113 
 114 	g_return_val_if_fail (text != NULL, NULL);
 115 	g_return_val_if_fail (find != NULL, NULL);
 116 	g_return_val_if_fail (*find, NULL);
 117 
 118 	find_len = strlen (find);
 119 	str = g_string_new ("");
 120 
 121 	p = text;
 122 	while (next = strstr (p, find), next) {
 123 		if (p < next)
 124 			g_string_append_len (str, p, next - p);
 125 
 126 		if (replace && *replace)
 127 			g_string_append (str, replace);
 128 
 129 		p = next + find_len;
 130 	}
 131 
 132 	g_string_append (str, p);
 133 
 134 	return str;
 135 }
 136 
 137 static const gchar *
 138 strip_home_dir (const gchar *dir)
 139 {
 140 	const gchar *home_dir, *res;
 141 
 142 	g_return_val_if_fail (dir != NULL, NULL);
 143 
 144 	home_dir = g_get_home_dir ();
 145 	g_return_val_if_fail (home_dir != NULL, dir);
 146 	g_return_val_if_fail (*home_dir != '\0', dir);
 147 
 148 	res = dir;
 149 	if (g_str_has_prefix (res, home_dir))
 150 		res += strlen (home_dir);
 151 
 152 	if (*res == G_DIR_SEPARATOR)
 153 		res++;
 154 
 155 	return res;
 156 }
 157 
 158 static GString *
 159 replace_variables (const gchar *str,
 160 		   gboolean remove_dir_sep)
 161 {
 162 	GString *res = NULL, *use;
 163 	const gchar *strip_datadir, *strip_configdir;
 164 
 165 	g_return_val_if_fail (str != NULL, NULL);
 166 
 167 	strip_datadir = strip_home_dir (e_get_user_data_dir ());
 168 	strip_configdir = strip_home_dir (e_get_user_config_dir ());
 169 
 170 	#define repl(_find, _replace)						\
 171 		use = replace_string (res ? res->str : str, _find, _replace);	\
 172 		g_return_val_if_fail (use != NULL, NULL);			\
 173 		if (res)							\
 174 			g_string_free (res, TRUE);				\
 175 		res = use;
 176 
 177 	repl ("$HOME", g_get_home_dir ());
 178 	repl ("$TMP", g_get_tmp_dir ());
 179 	repl ("$DATADIR", e_get_user_data_dir ());
 180 	repl ("$CONFIGDIR", e_get_user_config_dir ());
 181 	repl ("$STRIPDATADIR", strip_datadir);
 182 	repl ("$STRIPCONFIGDIR", strip_configdir);
 183 	repl ("$DBUSDATADIR", DBUS_SERVICES_DIR);
 184 
 185 	#undef repl
 186 
 187 	g_return_val_if_fail (res != NULL, NULL);
 188 
 189 	if (remove_dir_sep) {
 190 		/* remove trailing dir separator */
 191 		while (res->len > 0 && res->str[res->len - 1] == G_DIR_SEPARATOR) {
 192 			g_string_truncate (res, res->len - 1);
 193 		}
 194 	}
 195 
 196 	return res;
 197 }
 198 
 199 static void
 200 replace_in_file (const gchar *filename,
 201                  const gchar *find,
 202                  const gchar *replace)
 203 {
 204 	gchar *content = NULL;
 205 	GError *error = NULL;
 206 	GString *filenamestr = NULL;
 207 
 208 	g_return_if_fail (filename != NULL);
 209 	g_return_if_fail (find != NULL);
 210 	g_return_if_fail (*find);
 211 	g_return_if_fail (replace != NULL);
 212 
 213 	if (strstr (filename, "$")) {
 214 		filenamestr = replace_variables (filename, TRUE);
 215 
 216 		if (!filenamestr) {
 217 			g_warning (
 218 				"%s: Replace variables in '%s' failed!",
 219 				G_STRFUNC, filename);
 220 			return;
 221 		}
 222 
 223 		filename = filenamestr->str;
 224 	}
 225 
 226 	if (g_file_get_contents (filename, &content, NULL, &error)) {
 227 		GString *str = replace_string (content, find, replace);
 228 
 229 		if (str) {
 230 			if (!g_file_set_contents (filename, str->str, -1, &error) && error) {
 231 				g_warning (
 232 					"%s: cannot write file content, "
 233 					"error: %s", G_STRFUNC, error->message);
 234 				g_error_free (error);
 235 			}
 236 
 237 			g_string_free (str, TRUE);
 238 		} else {
 239 			g_warning (
 240 				"%s: Replace of '%s' to '%s' failed!",
 241 				G_STRFUNC, find, replace);
 242 		}
 243 
 244 		g_free (content);
 245 	} else if (error) {
 246 		g_warning (
 247 			"%s: Cannot read file content, error: %s",
 248 			G_STRFUNC, error->message);
 249 		g_error_free (error);
 250 	}
 251 
 252 	if (filenamestr)
 253 		g_string_free (filenamestr, TRUE);
 254 }
 255 
 256 static void
 257 run_cmd (const gchar *cmd)
 258 {
 259 	if (!cmd)
 260 		return;
 261 
 262 	if (strstr (cmd, "$") != NULL) {
 263 		/* read the doc for g_get_home_dir to know why replacing it here */
 264 		GString *str = replace_variables (cmd, FALSE);
 265 
 266 		if (str) {
 267 			print_and_run (str->str);
ignoring return value of 'system', declared with attribute warn_unused_result
(emitted by gcc)
268 g_string_free (str, TRUE); 269 } 270 } else 271 print_and_run (cmd);
ignoring return value of 'system', declared with attribute warn_unused_result
(emitted by gcc)
272 } 273 274 static void 275 run_evolution_no_wait (void) 276 { 277 g_spawn_command_line_async (EVOLUTION, NULL); 278 } 279 280 static void 281 write_dir_file (void) 282 { 283 GString *content, *filename; 284 GError *error = NULL; 285 286 filename = replace_variables ("$HOME/" EVOLUTION_DIR_FILE, TRUE); 287 g_return_if_fail (filename != NULL); 288 289 content = replace_variables ( 290 "[" KEY_FILE_GROUP "]\n" 291 "Version=" VERSION "\n" 292 "UserDataDir=$STRIPDATADIR\n" 293 "UserConfigDir=$STRIPCONFIGDIR\n" 294 , TRUE); 295 g_return_if_fail (content != NULL); 296 297 g_file_set_contents (filename->str, content->str, content->len, &error); 298 299 if (error) { 300 g_warning ("Failed to write file '%s': %s\n", filename->str, error->message); 301 g_error_free (error); 302 } 303 304 g_string_free (filename, TRUE); 305 g_string_free (content, TRUE); 306 } 307 308 static void 309 backup (const gchar *filename, 310 GCancellable *cancellable) 311 { 312 gchar *command; 313 gchar *quotedfname; 314 315 g_return_if_fail (filename && *filename); 316 quotedfname = g_shell_quote (filename); 317 318 if (g_cancellable_is_cancelled (cancellable)) 319 return; 320 321 txt = _("Shutting down Evolution"); 322 /* FIXME Will the versioned setting always work? */ 323 run_cmd (EVOLUTION " --quit"); 324 325 run_cmd ("rm $DATADIR/.running"); 326 327 if (g_cancellable_is_cancelled (cancellable)) 328 return; 329 330 txt = _("Backing Evolution accounts and settings"); 331 run_cmd ("dconf dump " DCONF_PATH_EDS " >" EVOLUTION_DIR DCONF_DUMP_FILE_EDS); 332 run_cmd ("dconf dump " DCONF_PATH_EVO " >" EVOLUTION_DIR DCONF_DUMP_FILE_EVO); 333 334 replace_in_file ( 335 EVOLUTION_DIR DCONF_DUMP_FILE_EDS, 336 e_get_user_data_dir (), EVOUSERDATADIR_MAGIC); 337 338 replace_in_file ( 339 EVOLUTION_DIR DCONF_DUMP_FILE_EVO, 340 e_get_user_data_dir (), EVOUSERDATADIR_MAGIC); 341 342 write_dir_file (); 343 344 if (g_cancellable_is_cancelled (cancellable)) 345 return; 346 347 txt = _("Backing Evolution data (Mails, Contacts, Calendar, Tasks, Memos)"); 348 349 /* FIXME stay on this file system ,other options?" */ 350 /* FIXME compression type?" */ 351 /* FIXME date/time stamp?" */ 352 /* FIXME backup location?" */ 353 command = g_strdup_printf ( 354 "cd $HOME && tar chf - $STRIPDATADIR " 355 "$STRIPCONFIGDIR " EVOLUTION_DIR_FILE " | " 356 "gzip > %s", quotedfname); 357 run_cmd (command); 358 g_free (command); 359 g_free (quotedfname); 360 361 run_cmd ("rm $HOME/" EVOLUTION_DIR_FILE); 362 363 txt = _("Back up complete"); 364 365 if (restart_arg) { 366 367 if (g_cancellable_is_cancelled (cancellable)) 368 return; 369 370 txt = _("Restarting Evolution"); 371 run_evolution_no_wait (); 372 } 373 374 } 375 376 static void 377 extract_backup_data (const gchar *filename, 378 gchar **restored_version, 379 gchar **data_dir, 380 gchar **config_dir) 381 { 382 GKeyFile *key_file; 383 GError *error = NULL; 384 385 g_return_if_fail (filename != NULL); 386 g_return_if_fail (data_dir != NULL); 387 g_return_if_fail (config_dir != NULL); 388 389 key_file = g_key_file_new (); 390 g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error); 391 392 if (error) { 393 g_warning ("Failed to read '%s': %s", filename, error->message); 394 g_error_free (error); 395 396 /* This is the current format as of Evolution 3.6. */ 397 } else if (g_key_file_has_group (key_file, KEY_FILE_GROUP)) { 398 gchar *tmp; 399 400 tmp = g_key_file_get_value ( 401 key_file, KEY_FILE_GROUP, "Version", NULL); 402 if (tmp != NULL) 403 *restored_version = g_strstrip (g_strdup (tmp)); 404 g_free (tmp); 405 406 tmp = g_key_file_get_value ( 407 key_file, KEY_FILE_GROUP, "UserDataDir", NULL); 408 if (tmp != NULL) 409 *data_dir = g_shell_quote (tmp); 410 g_free (tmp); 411 412 tmp = g_key_file_get_value ( 413 key_file, KEY_FILE_GROUP, "UserConfigDir", NULL); 414 if (tmp != NULL) 415 *config_dir = g_shell_quote (tmp); 416 g_free (tmp); 417 418 /* This is the legacy format with no version information. */ 419 } else if (g_key_file_has_group (key_file, "dirs")) { 420 gchar *tmp; 421 422 tmp = g_key_file_get_value (key_file, "dirs", "data", NULL); 423 if (tmp) 424 *data_dir = g_shell_quote (tmp); 425 g_free (tmp); 426 427 tmp = g_key_file_get_value (key_file, "dirs", "config", NULL); 428 if (tmp) 429 *config_dir = g_shell_quote (tmp); 430 g_free (tmp); 431 } 432 433 g_key_file_free (key_file); 434 } 435 436 static gint 437 get_dir_level (const gchar *dir) 438 { 439 gint res = 0, i; 440 441 g_return_val_if_fail (dir != NULL, -1); 442 443 for (i = 0; dir[i]; i++) { 444 if (dir[i] == '/' || dir[i] == '\\') 445 res++; 446 } 447 448 if (i > 0) 449 res++; 450 451 return res; 452 } 453 454 static gchar * 455 get_source_manager_reload_command (void) 456 { 457 GString *tmp; 458 gchar *command; 459 460 tmp = replace_variables (DBUS_SOURCE_REGISTRY_SERVICE_FILE, TRUE); 461 if (tmp) { 462 GKeyFile *key_file; 463 gchar *str = NULL; 464 465 key_file = g_key_file_new (); 466 if (g_key_file_load_from_file (key_file, tmp->str, G_KEY_FILE_NONE, NULL)) { 467 str = g_key_file_get_string (key_file, "D-BUS Service", "Name", NULL); 468 } 469 g_key_file_free (key_file); 470 471 if (str && *str) { 472 g_string_assign (tmp, str); 473 } else { 474 g_string_free (tmp, TRUE); 475 tmp = NULL; 476 } 477 478 g_free (str); 479 } 480 481 if (!tmp) 482 tmp = g_string_new ("org.gnome.evolution.dataserver.Sources0"); 483 484 command = g_strdup_printf ("gdbus call --session --dest %s " 485 "--object-path /org/gnome/evolution/dataserver/SourceManager " 486 "--method org.gnome.evolution.dataserver.SourceManager.Reload", 487 tmp->str); 488 489 g_string_free (tmp, TRUE); 490 491 return command; 492 } 493 494 static void 495 restore (const gchar *filename, 496 GCancellable *cancellable) 497 { 498 gchar *command; 499 gchar *quotedfname; 500 gboolean is_new_format = FALSE; 501 502 g_return_if_fail (filename && *filename); 503 504 if (!check (filename, &is_new_format)) { 505 g_message ("Cannot restore from an incorrect archive '%s'.", filename); 506 goto end; 507 } 508 509 quotedfname = g_shell_quote (filename); 510 511 if (g_cancellable_is_cancelled (cancellable)) 512 return; 513 514 /* FIXME Will the versioned setting always work? */ 515 txt = _("Shutting down Evolution"); 516 run_cmd (EVOLUTION " --quit"); 517 518 if (g_cancellable_is_cancelled (cancellable)) 519 return; 520 521 txt = _("Back up current Evolution data"); 522 run_cmd ("mv $DATADIR $DATADIR_old"); 523 run_cmd ("mv $CONFIGDIR $CONFIGDIR_old"); 524 525 if (g_cancellable_is_cancelled (cancellable)) 526 return; 527 528 txt = _("Extracting files from back up"); 529 530 if (is_new_format) { 531 GString *dir_fn; 532 gchar *data_dir = NULL; 533 gchar *config_dir = NULL; 534 gchar *restored_version = NULL; 535 536 command = g_strdup_printf ( 537 "cd $TMP && tar xzf %s " 538 EVOLUTION_DIR_FILE, quotedfname); 539 run_cmd (command); 540 g_free (command); 541 542 dir_fn = replace_variables ("$TMP" G_DIR_SEPARATOR_S EVOLUTION_DIR_FILE, TRUE); 543 if (!dir_fn) { 544 g_warning ("Failed to create evolution's dir filename"); 545 goto end; 546 } 547 548 /* data_dir and config_dir are quoted inside extract_backup_data */ 549 extract_backup_data ( 550 dir_fn->str, 551 &restored_version, 552 &data_dir, 553 &config_dir); 554 555 g_unlink (dir_fn->str); 556 g_string_free (dir_fn, TRUE); 557 558 if (!data_dir || !config_dir) { 559 g_warning ( 560 "Failed to get old data_dir (%p)/" 561 "config_dir (%p)", data_dir, config_dir); 562 g_free (data_dir); 563 g_free (config_dir); 564 goto end; 565 } 566 567 g_mkdir_with_parents (e_get_user_data_dir (), 0700); 568 g_mkdir_with_parents (e_get_user_config_dir (), 0700); 569 570 command = g_strdup_printf ( 571 "cd $DATADIR && tar xzf %s %s --strip-components=%d", 572 quotedfname, data_dir, get_dir_level (data_dir)); 573 run_cmd (command); 574 g_free (command); 575 576 command = g_strdup_printf ( 577 "cd $CONFIGDIR && tar xzf %s %s --strip-components=%d", 578 quotedfname, config_dir, get_dir_level (config_dir)); 579 run_cmd (command); 580 g_free (command); 581 582 /* If the back file had version information, set the last 583 * used version in GSettings before restarting Evolution. */ 584 if (restored_version != NULL && *restored_version != '\0') { 585 GSettings *settings; 586 587 settings = g_settings_new ("org.gnome.evolution"); 588 g_settings_set_string ( 589 settings, "version", restored_version); 590 g_object_unref (settings); 591 } 592 593 g_free (data_dir); 594 g_free (config_dir); 595 g_free (restored_version); 596 } else { 597 run_cmd ("mv $HOME/.evolution $HOME/.evolution_old"); 598 599 command = g_strdup_printf ( 600 "cd $HOME && gzip -cd %s | tar xf -", quotedfname); 601 run_cmd (command); 602 g_free (command); 603 } 604 605 g_free (quotedfname); 606 607 if (g_cancellable_is_cancelled (cancellable)) 608 return; 609 610 txt = _("Loading Evolution settings"); 611 612 if (is_new_format) { 613 /* new format has it in DATADIR... */ 614 GString *file = replace_variables (EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE, TRUE); 615 if (file && g_file_test (file->str, G_FILE_TEST_EXISTS)) { 616 /* ancient backup */ 617 replace_in_file ( 618 EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE, 619 EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); 620 run_cmd ("gconftool-2 --load " EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE); 621 622 /* give a chance to GConf to save what was loaded into a disk */ 623 g_usleep (G_USEC_PER_SEC * 5); 624 625 /* do not forget to convert GConf keys into GSettings */ 626 run_cmd ("gsettings-data-convert"); 627 run_cmd ("rm " EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE); 628 } else { 629 replace_in_file ( 630 EVOLUTION_DIR DCONF_DUMP_FILE_EDS, 631 EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); 632 run_cmd ("cat " EVOLUTION_DIR DCONF_DUMP_FILE_EDS " | dconf load " DCONF_PATH_EDS); 633 run_cmd ("rm " EVOLUTION_DIR DCONF_DUMP_FILE_EDS); 634 635 replace_in_file ( 636 EVOLUTION_DIR DCONF_DUMP_FILE_EVO, 637 EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); 638 run_cmd ("cat " EVOLUTION_DIR DCONF_DUMP_FILE_EVO " | dconf load " DCONF_PATH_EVO); 639 run_cmd ("rm " EVOLUTION_DIR DCONF_DUMP_FILE_EVO); 640 } 641 642 g_string_free (file, TRUE); 643 } else { 644 gchar *gconf_dump_file; 645 646 /* ... old format in ~/.evolution */ 647 gconf_dump_file = g_build_filename ( 648 "$HOME", ".evolution", ANCIENT_GCONF_DUMP_FILE, NULL); 649 650 replace_in_file ( 651 gconf_dump_file, 652 EVOUSERDATADIR_MAGIC, 653 e_get_user_data_dir ()); 654 655 command = g_strconcat ( 656 "gconftool-2 --load ", gconf_dump_file, NULL); 657 run_cmd (command); 658 g_free (command); 659 660 /* give a chance to GConf to save what was loaded into a disk */ 661 g_usleep (G_USEC_PER_SEC * 5); 662 663 /* do not forget to convert GConf keys into GSettings */ 664 run_cmd ("gsettings-data-convert"); 665 666 command = g_strconcat ("rm ", gconf_dump_file, NULL); 667 run_cmd (command); 668 g_free (command); 669 670 g_free (gconf_dump_file); 671 } 672 673 if (g_cancellable_is_cancelled (cancellable)) 674 return; 675 676 txt = _("Removing temporary back up files"); 677 run_cmd ("rm -rf $DATADIR_old"); 678 run_cmd ("rm -rf $CONFIGDIR_old"); 679 run_cmd ("rm $DATADIR/.running"); 680 681 if (!is_new_format) 682 run_cmd ("rm -rf $HOME/.evolution_old"); 683 684 if (g_cancellable_is_cancelled (cancellable)) 685 return; 686 687 txt = _("Reloading registry service"); 688 689 /* wait few seconds, till changes settle */ 690 g_usleep (G_USEC_PER_SEC * 5); 691 692 command = get_source_manager_reload_command (); 693 /* This runs migration routines on the newly-restored data. */ 694 run_cmd (command); 695 g_free (command); 696 697 end: 698 if (restart_arg) { 699 if (g_cancellable_is_cancelled (cancellable)) 700 return; 701 702 txt = _("Restarting Evolution"); 703 704 /* wait 5 seconds before restarting evolution, thus any 705 changes being done are updated in source registry too */ 706 g_usleep (G_USEC_PER_SEC * 5); 707 708 run_evolution_no_wait (); 709 } 710 } 711 712 static gboolean 713 check (const gchar *filename, 714 gboolean *is_new_format) 715 { 716 gchar *command; 717 gchar *quotedfname; 718 gboolean is_new = TRUE; 719 720 g_return_val_if_fail (filename && *filename, FALSE); 721 quotedfname = g_shell_quote (filename); 722 723 if (is_new_format) 724 *is_new_format = FALSE; 725 726 command = g_strdup_printf ("tar ztf %s 1>/dev/null", quotedfname); 727 result = system (command); 728 g_free (command); 729 730 g_message ("First result %d", result); 731 if (result) { 732 g_free (quotedfname); 733 return FALSE; 734 } 735 736 command = g_strdup_printf ( 737 "tar ztf %s | grep -e \"%s$\"", 738 quotedfname, EVOLUTION_DIR_FILE); 739 result = system (command); 740 g_free (command); 741 742 if (result) { 743 command = g_strdup_printf ( 744 "tar ztf %s | grep -e \"^\\.evolution/$\"", 745 quotedfname); 746 result = system (command); 747 g_free (command); 748 is_new = FALSE; 749 } 750 751 g_message ("Second result %d", result); 752 if (result) { 753 g_free (quotedfname); 754 return FALSE; 755 } 756 757 if (is_new) { 758 if (is_new_format) 759 *is_new_format = TRUE; 760 g_free (quotedfname); 761 return TRUE; 762 } 763 764 command = g_strdup_printf ( 765 "tar ztf %s | grep -e \"^\\.evolution/%s$\"", 766 quotedfname, ANCIENT_GCONF_DUMP_FILE); 767 result = system (command); 768 g_free (command); 769 770 if (result != 0) { 771 /* maybe it's an ancient backup */ 772 command = g_strdup_printf ( 773 "tar ztf %s | grep -e \"^\\.evolution/%s$\"", 774 quotedfname, ANCIENT_GCONF_DUMP_FILE); 775 result = system (command); 776 g_free (command); 777 } 778 779 g_free (quotedfname); 780 781 g_message ("Third result %d", result); 782 783 return result == 0; 784 } 785 786 static gboolean 787 pbar_update (GCancellable *cancellable) 788 { 789 gtk_progress_bar_pulse ((GtkProgressBar *) pbar); 790 gtk_progress_bar_set_text ((GtkProgressBar *) pbar, txt); 791 792 /* Return TRUE to reschedule the timeout. */ 793 return !g_cancellable_is_cancelled (cancellable); 794 } 795 796 static gboolean 797 finish_job (gpointer user_data) 798 { 799 gtk_main_quit (); 800 801 return FALSE; 802 } 803 804 static gboolean 805 start_job (GIOSchedulerJob *job, 806 GCancellable *cancellable, 807 gpointer user_data) 808 { 809 if (backup_op) 810 backup (bk_file, cancellable); 811 else if (restore_op) 812 restore (res_file, cancellable); 813 else if (check_op) 814 check (chk_file, NULL); /* not cancellable */ 815 816 g_io_scheduler_job_send_to_mainloop_async ( 817 job, finish_job, NULL, (GDestroyNotify) NULL); 818 819 return FALSE; 820 } 821 822 static void 823 dlg_response (GtkWidget *dlg, 824 gint response, 825 GCancellable *cancellable) 826 { 827 /* We will cancel only backup/restore 828 * operations and not the check operation. */ 829 g_cancellable_cancel (cancellable); 830 831 /* If the response is not of delete_event then destroy the event. */ 832 if (response != GTK_RESPONSE_NONE) 833 gtk_widget_destroy (dlg); 834 835 /* We will kill just the tar operation. Rest of 836 * them will be just a second of microseconds.*/ 837 run_cmd ("pkill tar"); 838 839 if (bk_file && backup_op && response == GTK_RESPONSE_REJECT) { 840 /* Backup was canceled, delete the 841 * backup file as it is not needed now. */ 842 gchar *cmd, *filename; 843 844 g_message ("Back up canceled, removing partial back up file."); 845 846 filename = g_shell_quote (bk_file); 847 cmd = g_strconcat ("rm ", filename, NULL); 848 849 run_cmd (cmd); 850 851 g_free (cmd); 852 g_free (filename); 853 } 854 855 gtk_main_quit (); 856 } 857 858 gint 859 main (gint argc, 860 gchar **argv) 861 { 862 GCancellable *cancellable; 863 gchar *file = NULL, *oper = NULL; 864 const gchar *title = NULL; 865 gint ii; 866 GError *error = NULL; 867 868 #ifdef G_OS_WIN32 869 /* Reduce risks */ 870 { 871 typedef BOOL (WINAPI *t_SetDllDirectoryA) (LPCSTR lpPathName); 872 t_SetDllDirectoryA p_SetDllDirectoryA; 873 874 p_SetDllDirectoryA = GetProcAddress ( 875 GetModuleHandle ("kernel32.dll"), 876 "SetDllDirectoryA"); 877 878 if (p_SetDllDirectoryA != NULL) 879 p_SetDllDirectoryA (""); 880 } 881 #ifndef _WIN64 882 { 883 typedef BOOL (WINAPI *t_SetProcessDEPPolicy) (DWORD dwFlags); 884 t_SetProcessDEPPolicy p_SetProcessDEPPolicy; 885 886 p_SetProcessDEPPolicy = GetProcAddress ( 887 GetModuleHandle ("kernel32.dll"), 888 "SetProcessDEPPolicy"); 889 890 if (p_SetProcessDEPPolicy) 891 p_SetProcessDEPPolicy ( 892 PROCESS_DEP_ENABLE | 893 PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION); 894 } 895 #endif 896 #endif 897 898 bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); 899 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); 900 textdomain (GETTEXT_PACKAGE); 901 902 gtk_init_with_args ( 903 &argc, &argv, NULL, options, GETTEXT_PACKAGE, &error); 904 905 if (error != NULL) { 906 g_printerr ("%s\n", error->message); 907 g_error_free (error); 908 exit (EXIT_FAILURE); 909 } 910 911 if (opt_remaining != NULL) { 912 for (ii = 0; ii < g_strv_length (opt_remaining); ii++) { 913 if (backup_op) { 914 title = _("Evolution Back Up"); 915 oper = _("Backing up to the folder %s"); 916 bk_file = g_strdup ((gchar *) opt_remaining[ii]); 917 file = bk_file; 918 } else if (restore_op) { 919 title = _("Evolution Restore"); 920 oper = _("Restoring from the folder %s"); 921 res_file = g_strdup ((gchar *) opt_remaining[ii]); 922 file = res_file; 923 } else if (check_op) { 924 d (g_message ("Checking %s", (gchar *) opt_remaining[ii])); 925 chk_file = g_strdup ((gchar *) opt_remaining[ii]); 926 } 927 } 928 } 929 930 cancellable = g_cancellable_new (); 931 932 if (gui_arg && !check_op) { 933 GtkWidget *widget, *container; 934 GtkWidget *action_area; 935 GtkWidget *content_area; 936 const gchar *txt, *txt2; 937 gchar *str = NULL; 938 gchar *markup; 939 940 gtk_window_set_default_icon_name ("evolution"); 941 942 /* Backup / Restore only can have GUI. 943 * We should restrict the rest. */ 944 progress_dialog = gtk_dialog_new_with_buttons ( 945 title, NULL, 946 GTK_DIALOG_MODAL, 947 GTK_STOCK_CANCEL, 948 GTK_RESPONSE_REJECT, 949 NULL); 950 951 gtk_container_set_border_width ( 952 GTK_CONTAINER (progress_dialog), 12); 953 954 action_area = gtk_dialog_get_action_area ( 955 GTK_DIALOG (progress_dialog)); 956 content_area = gtk_dialog_get_content_area ( 957 GTK_DIALOG (progress_dialog)); 958 959 /* Override GtkDialog defaults */ 960 gtk_box_set_spacing (GTK_BOX (content_area), 12); 961 gtk_container_set_border_width (GTK_CONTAINER (content_area), 0); 962 gtk_box_set_spacing (GTK_BOX (action_area), 12); 963 gtk_container_set_border_width (GTK_CONTAINER (action_area), 0); 964 965 if (oper && file) 966 str = g_strdup_printf (oper, file); 967 968 container = gtk_grid_new (); 969 gtk_grid_set_column_spacing (GTK_GRID (container), 6); 970 gtk_grid_set_row_spacing (GTK_GRID (container), 0); 971 gtk_widget_show (container); 972 973 gtk_box_pack_start ( 974 GTK_BOX (content_area), container, FALSE, TRUE, 0); 975 976 widget = gtk_image_new_from_stock ( 977 GTK_STOCK_COPY, GTK_ICON_SIZE_DIALOG); 978 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); 979 gtk_widget_show (widget); 980 981 gtk_grid_attach (GTK_GRID (container), widget, 0, 0, 1, 3); 982 g_object_set (G_OBJECT (widget), 983 "halign", GTK_ALIGN_FILL, 984 "valign", GTK_ALIGN_FILL, 985 "vexpand", TRUE, 986 NULL); 987 988 if (backup_op) { 989 txt = _("Backing up Evolution Data"); 990 txt2 = _("Please wait while Evolution is backing up your data."); 991 } else if (restore_op) { 992 txt = _("Restoring Evolution Data"); 993 txt2 = _("Please wait while Evolution is restoring your data."); 994 } else { 995 g_return_val_if_reached (EXIT_FAILURE); 996 } 997 998 markup = g_markup_printf_escaped ("<b><big>%s</big></b>", txt); 999 widget = gtk_label_new (markup); 1000 gtk_label_set_line_wrap (GTK_LABEL (widget), FALSE); 1001 gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); 1002 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.0); 1003 gtk_widget_show (widget); 1004 g_free (markup); 1005 1006 gtk_grid_attach (GTK_GRID (container), widget, 1, 0, 1, 1); 1007 g_object_set (G_OBJECT (widget), 1008 "halign", GTK_ALIGN_FILL, 1009 "hexpand", TRUE, 1010 "valign", GTK_ALIGN_FILL, 1011 NULL); 1012 1013 markup = g_strconcat ( 1014 txt2, " ", _("This may take a while depending " 1015 "on the amount of data in your account."), NULL); 1016 widget = gtk_label_new (markup); 1017 gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE); 1018 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); 1019 gtk_widget_show (widget); 1020 g_free (markup); 1021 1022 gtk_grid_attach (GTK_GRID (container), widget, 1, 1, 1, 1); 1023 g_object_set (G_OBJECT (widget), 1024 "halign", GTK_ALIGN_FILL, 1025 "hexpand", TRUE, 1026 "valign", GTK_ALIGN_FILL, 1027 NULL); 1028 1029 pbar = gtk_progress_bar_new (); 1030 1031 if (str != NULL) { 1032 markup = g_markup_printf_escaped ("<i>%s</i>", str); 1033 widget = gtk_label_new (markup); 1034 gtk_label_set_use_markup (GTK_LABEL (widget), TRUE); 1035 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); 1036 g_free (markup); 1037 g_free (str); 1038 1039 gtk_grid_attach (GTK_GRID (container), widget, 1, 2, 1, 1); 1040 g_object_set (G_OBJECT (widget), 1041 "halign", GTK_ALIGN_FILL, 1042 "hexpand", TRUE, 1043 "valign", GTK_ALIGN_FILL, 1044 NULL); 1045 1046 gtk_grid_attach (GTK_GRID (container), pbar, 1, 3, 1, 1); 1047 } else 1048 gtk_grid_attach (GTK_GRID (container), pbar, 1, 2, 1, 1); 1049 1050 g_object_set (G_OBJECT (pbar), 1051 "halign", GTK_ALIGN_FILL, 1052 "hexpand", TRUE, 1053 "valign", GTK_ALIGN_FILL, 1054 NULL); 1055 1056 g_signal_connect ( 1057 progress_dialog, "response", 1058 G_CALLBACK (dlg_response), cancellable); 1059 gtk_widget_show_all (progress_dialog); 1060 1061 } else if (check_op) { 1062 /* For sanity we don't need gui */ 1063 check (chk_file, NULL); 1064 exit (result == 0 ? 0 : 1); 1065 } 1066 1067 if (gui_arg) 1068 g_timeout_add_full ( 1069 G_PRIORITY_DEFAULT, 50, 1070 (GSourceFunc) pbar_update, 1071 g_object_ref (cancellable), 1072 (GDestroyNotify) g_object_unref); 1073 1074 g_io_scheduler_push_job ( 1075 start_job, NULL, 1076 (GDestroyNotify) NULL, 1077 G_PRIORITY_DEFAULT, cancellable); 1078 1079 gtk_main (); 1080 1081 g_object_unref (cancellable); 1082 1083 return result; 1084 }