From: <svn...@op...> - 2009-09-29 23:21:03
|
Author: cdfrey Date: Wed Sep 30 01:20:47 2009 New Revision: 5860 URL: http://www.opensync.org/changeset/5860 Log: opensync_group_env.c: added 0.22 -> 0.40 copy upgrade behaviour The first time that opensync runs and creates its default directory (which will not exist on any pure 0.22 system because the new default directory has a version number in it) opensync will search for old 0.22 group configs in the ~/.opensync directory, and if found, copy them all to the new $XDG_CONFIG_HOME (~/.config/opensync/0.40) directory. After this copy is complete, it is safe to run OSyncUpdater on the new 0.40 config directory. Note: this patch contains two generic functions: osync_glob_copy() and osync_copy_file() which perhaps should be moved into somewhere genericly useful. The OSyncUpdater code could possibly use these functions too... they were based on OSyncUpdater code. Modified: trunk/opensync/group/opensync_group_env.c Modified: trunk/opensync/group/opensync_group_env.c ============================================================================== --- trunk/opensync/group/opensync_group_env.c Wed Sep 30 01:19:39 2009 (r5859) +++ trunk/opensync/group/opensync_group_env.c Wed Sep 30 01:20:47 2009 (r5860) @@ -136,6 +136,152 @@ return g_mkdir_with_parents(full_path, 0700); } +static osync_bool osync_copy_file(const char *srcdir, const char *filename, const char *destdir, OSyncError **error) +{ + char *path = NULL; + char *destpath = NULL; + gchar *content = NULL; + osync_bool ret = FALSE; + gsize length; + GError *gerror = NULL; + + path = osync_strdup_printf("%s%c%s", srcdir, G_DIR_SEPARATOR, filename); + destpath = osync_strdup_printf("%s%c%s", destdir, G_DIR_SEPARATOR, filename); + + if (!g_file_get_contents(path, &content, &length, &gerror)) { + osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Failed reading file '%s': %s", path, gerror->message); + g_error_free(gerror); + goto destroy; + } + + if (!g_file_set_contents(destpath, content, length, &gerror)) { + osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Failed writing file '%s': %s", destpath, gerror->message); + g_error_free(gerror); + goto destroy; + } + + /* success */ + ret = TRUE; + +destroy: + if (content) + g_free(content); + if (destpath) + osync_free(destpath); + if (path) + osync_free(path); + return ret; +} + +/* copies all matching files and subdirectories, recursively */ +static osync_bool osync_glob_copy(const char *srcdir, const char *glob, const char *destdir, OSyncError **error) +{ + GDir *dir = NULL; + GError *gerror = NULL; + const char *name = NULL; + osync_bool ret = FALSE; + GPatternSpec *pattern = NULL; + char *path = NULL; + char *newdestdir = NULL; + + dir = g_dir_open(srcdir, 0, &gerror); + if (!dir) { + osync_error_set(error, OSYNC_ERROR_IO_ERROR, "Unable to open source directory '%s' for copy: %s", srcdir, gerror->message); + g_error_free(gerror); + return FALSE; + } + + pattern = g_pattern_spec_new(glob); + if (!pattern) + goto destroy; + + while ((name = g_dir_read_name(dir))) { + if (g_pattern_match_string(pattern, name)) { + path = osync_strdup_printf("%s%c%s", srcdir, G_DIR_SEPARATOR, name); + + /* copy file */ + if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { + if (!osync_copy_file(srcdir, name, destdir, error)) + goto destroy; + } + /* copy subdirectory */ + else if (g_file_test(path, G_FILE_TEST_IS_DIR)) { + newdestdir = osync_strdup_printf("%s%c%s", destdir, G_DIR_SEPARATOR, name); + + if (g_mkdir(newdestdir, 0755) < 0 ) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to create directory at %s: %s", newdestdir, g_strerror(errno)); + goto destroy; + } + + if (!osync_glob_copy(path, "*", newdestdir, error)) + goto destroy; + + osync_free(newdestdir); + newdestdir = NULL; + } + + osync_free(path); + path = NULL; + } + } + + /* success */ + ret = TRUE; + +destroy: + if (newdestdir) + osync_free(newdestdir); + if (path) + osync_free(path); + if (pattern) + g_pattern_spec_free(pattern); + g_dir_close(dir); + return ret; +} + +/* This function assumes that the default config dir does not yet + * exist, and so creates it in the XDG_CONFIG_HOME compatible location, + * and copies all existing 0.22 group directories into it, if an 0.22 + * config is found. This function only looks in the ~/.opensync + * directory for 0.22 group configs. + * + * After this function completes, it is safe to run OSyncUpdater on + * the new 0.40 config directory. + */ +static osync_bool osync_group_env_setup_config_dir(const char *groupsdir, OSyncError **error) +{ + const char *homedir = NULL; + char *osync22dir = NULL; + osync_bool ret = FALSE; + + if (osync_xdg_make_config_dir(groupsdir) < 0) { + osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to create group directory at %s: %s", groupsdir, g_strerror(errno)); + goto destroy; + } + + /* find an opensync 0.22 directory */ + /* Use $HOME instead of passwd home, in case someone runs + * with OpenSync with sudo. The behaviour of sudo might + * differ on different systems, depending on the sudoers + * configuration. For more details see ticket #751 + */ + homedir = g_getenv("HOME"); + if (homedir == NULL) + homedir = g_get_home_dir(); + + osync22dir = osync_strdup_printf("%s%c.opensync", homedir, G_DIR_SEPARATOR); + if (!osync_glob_copy(osync22dir, "group*", groupsdir, error)) + goto destroy; + + osync_trace(TRACE_INTERNAL, "Created groups configdir %s\n", groupsdir); + ret = TRUE; + +destroy: + if (osync22dir) + osync_free(osync22dir); + return ret; +} + osync_bool osync_group_env_load_groups(OSyncGroupEnv *env, const char *path, OSyncError **error) { GDir *dir = NULL; @@ -158,11 +304,8 @@ osync_free(homedir); if (!g_file_test(env->groupsdir, G_FILE_TEST_EXISTS)) { - if (osync_xdg_make_config_dir(env->groupsdir) < 0) { - osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to create group directory at %s: %s", env->groupsdir, g_strerror(errno)); + if (!osync_group_env_setup_config_dir(env->groupsdir, error)) goto error_free_path; - } - osync_trace(TRACE_INTERNAL, "Created groups configdir %s\n", env->groupsdir); } } else { if (!g_path_is_absolute(path)) { |