static void shell_xdg_migrate_config_dir_mail (EShell *shell, const gchar *old_base_dir) { const gchar *user_config_dir; gchar *old_config_dir; gchar *new_config_dir; gchar *old_filename; gchar *new_filename; user_config_dir = e_get_user_config_dir (); old_config_dir = g_build_filename (old_base_dir, "mail", NULL); new_config_dir = g_build_filename (user_config_dir, "mail", NULL); old_filename = g_build_filename (old_config_dir, "filters.xml", NULL); new_filename = g_build_filename (new_config_dir, "filters.xml", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); old_filename = g_build_filename (old_config_dir, "vfolders.xml", NULL); new_filename = g_build_filename (new_config_dir, "vfolders.xml", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* I hate this file. GtkHtml uses style properties for fonts. */ old_filename = g_build_filename ( old_config_dir, "config", "gtkrc-mail-fonts", NULL); new_filename = g_build_filename ( new_config_dir, "gtkrc-mail-fonts", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* This file is no longer used. Try removing it. */ old_filename = g_build_filename ( old_config_dir, "config", "folder-tree-expand-state.xml", NULL); g_unlink (old_filename); g_free (old_filename); /* Everything else in the "config" directory just should be * per-folder ETree files recording the expanded state of mail * threads. Rename this directory to "folders". */ old_filename = g_build_filename (old_config_dir, "config", NULL); new_filename = g_build_filename (new_config_dir, "folders", NULL); shell_xdg_migrate_rename_files (old_filename, new_filename); g_free (old_filename); g_free (new_filename); g_free (old_config_dir); g_free (new_config_dir); }
static GString * replace_variables (const gchar *str, gboolean remove_dir_sep) { GString *res = NULL, *use; const gchar *strip_datadir, *strip_configdir; g_return_val_if_fail (str != NULL, NULL); strip_datadir = strip_home_dir (e_get_user_data_dir ()); strip_configdir = strip_home_dir (e_get_user_config_dir ()); #define repl(_find, _replace) \ use = e_str_replace_string (res ? res->str : str, _find, _replace); \ g_return_val_if_fail (use != NULL, NULL); \ if (res) \ g_string_free (res, TRUE); \ res = use; repl ("$HOME", g_get_home_dir ()); repl ("$TMP", g_get_tmp_dir ()); repl ("$DATADIR", e_get_user_data_dir ()); repl ("$CONFIGDIR", e_get_user_config_dir ()); repl ("$STRIPDATADIR", strip_datadir); repl ("$STRIPCONFIGDIR", strip_configdir); repl ("$DBUSDATADIR", DBUS_SERVICES_DIR); #undef repl g_return_val_if_fail (res != NULL, NULL); if (remove_dir_sep) { /* remove trailing dir separator */ while (res->len > 0 && res->str[res->len - 1] == G_DIR_SEPARATOR) { g_string_truncate (res, res->len - 1); } } return res; }
static void shell_xdg_migrate_config_dir (EShell *shell, const gchar *old_base_dir) { const gchar *old_config_dir; const gchar *new_config_dir; gchar *old_filename; gchar *new_filename; gint ii; g_print ("Migrating config data\n"); /* Some files are common to all shell backends. */ for (ii = 0; shell_backend_names[ii] != NULL; ii++) shell_xdg_migrate_config_dir_common ( shell, old_base_dir, shell_backend_names[ii]); /* Handle backend-specific files. */ shell_xdg_migrate_config_dir_mail (shell, old_base_dir); /* Remove leftover config directories. */ for (ii = 0; shell_backend_names[ii] != NULL; ii++) { shell_xdg_migrate_dir_cleanup ( shell, old_base_dir, shell_backend_names[ii], "config"); shell_xdg_migrate_dir_cleanup ( shell, old_base_dir, shell_backend_names[ii], "views"); } /*** Miscellaneous configuration files. ***/ old_config_dir = old_base_dir; new_config_dir = e_get_user_config_dir (); /* Subtle name change: datetime-formats --> datetime-formats.ini */ old_filename = g_build_filename (old_config_dir, "datetime-formats", NULL); new_filename = g_build_filename (new_config_dir, "datetime-formats.ini", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* Subtle name change: printing --> printing.ini */ old_filename = g_build_filename (old_config_dir, "printing", NULL); new_filename = g_build_filename (new_config_dir, "printing.ini", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); }
static void restore (const gchar *filename, GCancellable *cancellable) { gchar *command; gchar *quotedfname; gboolean is_new_format = FALSE; g_return_if_fail (filename && *filename); if (!check (filename, &is_new_format)) { g_message ("Cannot restore from an incorrect archive '%s'.", filename); goto end; } quotedfname = g_shell_quote (filename); if (g_cancellable_is_cancelled (cancellable)) return; /* FIXME Will the versioned setting always work? */ txt = _("Shutting down Evolution"); run_cmd (EVOLUTION " --quit"); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Back up current Evolution data"); run_cmd ("mv $DATADIR $DATADIR_old"); run_cmd ("mv $CONFIGDIR $CONFIGDIR_old"); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Extracting files from back up"); if (is_new_format) { GString *dir_fn; gchar *data_dir = NULL; gchar *config_dir = NULL; gchar *restored_version = NULL; const gchar *tar_opts; if (get_filename_is_xz (filename)) tar_opts = "-xJf"; else tar_opts = "-xzf"; command = g_strdup_printf ( "cd $TMP && tar %s %s " EVOLUTION_DIR_FILE, tar_opts, quotedfname); run_cmd (command); g_free (command); dir_fn = replace_variables ("$TMP" G_DIR_SEPARATOR_S EVOLUTION_DIR_FILE, TRUE); if (!dir_fn) { g_warning ("Failed to create evolution's dir filename"); goto end; } /* data_dir and config_dir are quoted inside extract_backup_data */ extract_backup_data ( dir_fn->str, &restored_version, &data_dir, &config_dir); g_unlink (dir_fn->str); g_string_free (dir_fn, TRUE); if (!data_dir || !config_dir) { g_warning ( "Failed to get old data_dir (%p)/" "config_dir (%p)", data_dir, config_dir); g_free (data_dir); g_free (config_dir); goto end; } g_mkdir_with_parents (e_get_user_data_dir (), 0700); g_mkdir_with_parents (e_get_user_config_dir (), 0700); command = g_strdup_printf ( "cd $DATADIR && tar --strip-components %d %s %s %s", get_dir_level (data_dir), tar_opts, quotedfname, data_dir); run_cmd (command); g_free (command); command = g_strdup_printf ( "cd $CONFIGDIR && tar --strip-components %d %s %s %s", get_dir_level (config_dir), tar_opts, quotedfname, config_dir); run_cmd (command); g_free (command); /* If the back file had version information, set the last * used version in GSettings before restarting Evolution. */ if (restored_version != NULL && *restored_version != '\0') { GSettings *settings; settings = e_util_ref_settings ("org.gnome.evolution"); g_settings_set_string ( settings, "version", restored_version); g_object_unref (settings); } g_free (data_dir); g_free (config_dir); g_free (restored_version); } else { const gchar *decr_opts; if (get_filename_is_xz (filename)) decr_opts = "xz -cd"; else decr_opts = "gzip -cd"; run_cmd ("mv $HOME/.evolution $HOME/.evolution_old"); command = g_strdup_printf ( "cd $HOME && %s %s | tar xf -", decr_opts, quotedfname); run_cmd (command); g_free (command); } g_free (quotedfname); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Loading Evolution settings"); if (is_new_format) { /* new format has it in DATADIR... */ GString *file = replace_variables (EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE, TRUE); if (file && g_file_test (file->str, G_FILE_TEST_EXISTS)) { unset_eds_migrated_flag (); /* ancient backup */ replace_in_file ( EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); run_cmd ("gconftool-2 --load " EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE); /* give a chance to GConf to save what was loaded into a disk */ g_usleep (G_USEC_PER_SEC * 5); /* do not forget to convert GConf keys into GSettings */ run_cmd ("gsettings-data-convert"); run_cmd ("rm " EVOLUTION_DIR ANCIENT_GCONF_DUMP_FILE); } else { replace_in_file ( EVOLUTION_DIR DCONF_DUMP_FILE_EDS, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); run_cmd ("cat " EVOLUTION_DIR DCONF_DUMP_FILE_EDS " | dconf load " DCONF_PATH_EDS); run_cmd ("rm " EVOLUTION_DIR DCONF_DUMP_FILE_EDS); replace_in_file ( EVOLUTION_DIR DCONF_DUMP_FILE_EVO, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); run_cmd ("cat " EVOLUTION_DIR DCONF_DUMP_FILE_EVO " | dconf load " DCONF_PATH_EVO); run_cmd ("rm " EVOLUTION_DIR DCONF_DUMP_FILE_EVO); } g_string_free (file, TRUE); } else { gchar *gconf_dump_file; unset_eds_migrated_flag (); /* ... old format in ~/.evolution */ gconf_dump_file = g_build_filename ( "$HOME", ".evolution", ANCIENT_GCONF_DUMP_FILE, NULL); replace_in_file ( gconf_dump_file, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); command = g_strconcat ( "gconftool-2 --load ", gconf_dump_file, NULL); run_cmd (command); g_free (command); /* give a chance to GConf to save what was loaded into a disk */ g_usleep (G_USEC_PER_SEC * 5); /* do not forget to convert GConf keys into GSettings */ run_cmd ("gsettings-data-convert"); command = g_strconcat ("rm ", gconf_dump_file, NULL); run_cmd (command); g_free (command); g_free (gconf_dump_file); } if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Removing temporary back up files"); run_cmd ("rm -rf $DATADIR_old"); run_cmd ("rm -rf $CONFIGDIR_old"); run_cmd ("rm $DATADIR/.running"); if (!is_new_format) run_cmd ("rm -rf $HOME/.evolution_old"); if (g_cancellable_is_cancelled (cancellable)) return; /* Make full-restart background processes after restore */ run_cmd (EVOLUTION " --force-shutdown"); txt = _("Reloading registry service"); /* wait few seconds, till changes settle */ g_usleep (G_USEC_PER_SEC * 5); command = get_source_manager_reload_command (); /* This runs migration routines on the newly-restored data. */ run_cmd (command); g_free (command); end: if (restart_arg) { if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Restarting Evolution"); /* wait 5 seconds before restarting evolution, thus any * changes being done are updated in source registry too */ g_usleep (G_USEC_PER_SEC * 5); run_evolution_no_wait (); } }
static gchar * ep_key_file_get_filename (void) { return g_build_filename ( e_get_user_config_dir (), "credentials", "Passwords", NULL); }
static void shell_xdg_migrate_config_dir_common (EShell *shell, const gchar *old_base_dir, const gchar *backend_name) { GDir *dir; const gchar *user_config_dir; gchar *old_config_dir; gchar *new_config_dir; gchar *old_filename; gchar *new_filename; gchar *dirname; user_config_dir = e_get_user_config_dir (); old_config_dir = g_build_filename (old_base_dir, backend_name, NULL); new_config_dir = g_build_filename (user_config_dir, backend_name, NULL); g_mkdir_with_parents (new_config_dir, 0700); old_filename = g_build_filename (old_config_dir, "views", NULL); new_filename = g_build_filename (new_config_dir, "views", NULL); shell_xdg_migrate_rename_files (old_filename, new_filename); g_free (old_filename); g_free (new_filename); old_filename = g_build_filename (old_config_dir, "searches.xml", NULL); new_filename = g_build_filename (new_config_dir, "searches.xml", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* This one only occurs in calendar and memos. * For other backends this will just be a no-op. */ old_filename = g_build_filename ( old_config_dir, "config", "MemoPad", NULL); new_filename = g_build_filename (new_config_dir, "MemoPad", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* This one only occurs in calendar and tasks. * For other backends this will just be a no-op. */ old_filename = g_build_filename ( old_config_dir, "config", "TaskPad", NULL); new_filename = g_build_filename (new_config_dir, "TaskPad", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* Subtle name change: config/state --> state.ini */ old_filename = g_build_filename (old_config_dir, "config", "state", NULL); new_filename = g_build_filename (new_config_dir, "state.ini", NULL); shell_xdg_migrate_rename (old_filename, new_filename); g_free (old_filename); g_free (new_filename); /* GIO had a bug for awhile where it would leave behind an empty * temp file with the pattern .goutputstream-XXXXXX if an output * stream operation was cancelled. We've had several reports of * these files in config directories, so remove any we find. */ dirname = g_build_filename (old_config_dir, "config", NULL); dir = g_dir_open (dirname, 0, NULL); if (dir != NULL) { const gchar *basename; while ((basename = g_dir_read_name (dir)) != NULL) { gchar *filename; struct stat st; if (!g_str_has_prefix (basename, ".goutputstream")) continue; filename = g_build_filename (dirname, basename, NULL); /* Verify the file is indeed empty. */ if (g_stat (filename, &st) == 0 && st.st_size == 0) g_unlink (filename); g_free (filename); } g_dir_close (dir); } g_free (dirname); g_free (old_config_dir); g_free (new_config_dir); }
static void restore (const gchar *filename, GCancellable *cancellable) { gchar *command; gchar *quotedfname; gboolean is_new_format = FALSE; g_return_if_fail (filename && *filename); if (!check (filename, &is_new_format)) { g_message ("Cannot restore from an incorrect archive '%s'.", filename); goto end; } quotedfname = g_shell_quote (filename); if (g_cancellable_is_cancelled (cancellable)) return; /* FIXME Will the versioned setting always work? */ txt = _("Shutting down Evolution"); run_cmd (EVOLUTION " --quit"); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Back up current Evolution data"); run_cmd ("mv $DATADIR $DATADIR_old"); run_cmd ("mv $CONFIGDIR $CONFIGDIR_old"); run_cmd ("mv $HOME/.camel_certs $HOME/.camel_certs_old"); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Extracting files from back up"); if (is_new_format) { GString *dir_fn; gchar *data_dir = NULL, *config_dir = NULL; command = g_strdup_printf ( "cd $TMP && tar xzf %s " EVOLUTION_DIR_FILE, quotedfname); run_cmd (command); g_free (command); dir_fn = replace_variables ("$TMP" G_DIR_SEPARATOR_S EVOLUTION_DIR_FILE); if (!dir_fn) { g_warning ("Failed to create evolution's dir filename"); goto end; } /* data_dir and config_dir are quoted inside extract_backup_dirs */ extract_backup_dirs (dir_fn->str, &data_dir, &config_dir); g_unlink (dir_fn->str); g_string_free (dir_fn, TRUE); if (!data_dir || !config_dir) { g_warning ("Failed to get old data_dir (%p)/config_dir (%p)", data_dir, config_dir); g_free (data_dir); g_free (config_dir); goto end; } g_mkdir_with_parents (e_get_user_data_dir (), 0700); g_mkdir_with_parents (e_get_user_config_dir (), 0700); command = g_strdup_printf ( "cd $DATADIR && tar xzf %s %s --strip-components=%d", quotedfname, data_dir, get_dir_level (data_dir)); run_cmd (command); g_free (command); command = g_strdup_printf ( "cd $CONFIGDIR && tar xzf %s %s --strip-components=%d", quotedfname, config_dir, get_dir_level (config_dir)); run_cmd (command); g_free (command); command = g_strdup_printf ( "cd $HOME && tar xzf %s .camel_certs", quotedfname); run_cmd (command); g_free (command); g_free (data_dir); g_free (config_dir); } else { run_cmd ("mv $HOME/.evolution $HOME/.evolution_old"); command = g_strdup_printf ( "cd $HOME && gzip -cd %s | tar xf -", quotedfname); run_cmd (command); g_free (command); } g_free (quotedfname); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Loading Evolution settings"); if (is_new_format) { /* new format has it in DATADIR... */ replace_in_file ( EVOLUTION_DIR GCONF_DUMP_FILE, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); run_cmd ("gconftool-2 --load " EVOLUTION_DIR GCONF_DUMP_FILE); run_cmd ("rm " EVOLUTION_DIR GCONF_DUMP_FILE); } else { gchar *gconf_dump_file; /* ... old format in ~/.evolution */ gconf_dump_file = g_build_filename ( "$HOME", ".evolution", GCONF_DUMP_FILE, NULL); replace_in_file ( gconf_dump_file, EVOUSERDATADIR_MAGIC, e_get_user_data_dir ()); command = g_strconcat ( "gconftool-2 --load ", gconf_dump_file, NULL); run_cmd (command); g_free (command); command = g_strconcat ("rm ", gconf_dump_file, NULL); run_cmd (command); g_free (command); g_free (gconf_dump_file); } if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Removing temporary back up files"); run_cmd ("rm -rf $DATADIR_old"); run_cmd ("rm -rf $CONFIGDIR_old"); run_cmd ("rm -rf $HOME/.camel_certs_old"); run_cmd ("rm $DATADIR/.running"); if (!is_new_format) run_cmd ("rm -rf $HOME/.evolution_old"); if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Ensuring local sources"); end: if (restart_arg) { if (g_cancellable_is_cancelled (cancellable)) return; txt = _("Restarting Evolution"); run_evolution_no_wait (); } }
gint main (gint argc, gchar **argv) { GFile *pid_file; GFileMonitor *monitor; const gchar *user_config_dir; gchar *filename; GError *error = NULL; bindtextdomain (GETTEXT_PACKAGE, EVOLUTION_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); g_type_init (); user_config_dir = e_get_user_config_dir (); filename = g_build_filename (user_config_dir, ".running", NULL); pid_file = g_file_new_for_path (filename); g_free (filename); if (!get_evolution_pid (pid_file)) { g_printerr ("Could not find Evolution's process ID\n"); kill_factories (); exit (EXIT_FAILURE); } if (g_getenv ("DISPLAY") == NULL) { #ifdef KILL_PROCESS_CMD system (KILL_PROCESS_CMD " -QUIT evolution 2> /dev/null"); #endif } else { /* Play it safe here and bail if something goes wrong. We don't * want to just skip to the killing if we can't ask Evolution to * terminate gracefully. Despite our name we actually want to * -avoid- killing Evolution if at all possible. */ if (!g_spawn_command_line_async ("evolution --quit", &error)) { g_printerr ("%s", error->message); g_error_free (error); kill_factories (); exit (EXIT_FAILURE); } } /* Now we set up a monitor on Evolution's .running file. * If Evolution is still responsive it will delete this * file just before terminating and we'll be notified. */ monitor = g_file_monitor_file (pid_file, 0, NULL, &error); if (error != NULL) { g_printerr ("%s", error->message); g_error_free (error); kill_factories (); exit (EXIT_FAILURE); } g_signal_connect ( monitor, "changed", G_CALLBACK (file_monitor_changed_cb), NULL); g_timeout_add_seconds ( EVOLUTION_SHUTDOWN_TIMEOUT, (GSourceFunc) evolution_not_responding_cb, NULL); /* Start the clock. */ main_loop = g_main_loop_new (NULL, TRUE); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); g_object_unref (monitor); kill_factories (); return EXIT_SUCCESS; }