diff --git a/include/util.h b/include/util.h index 9d14af9..c6a33c0 100644 --- a/include/util.h +++ b/include/util.h @@ -162,6 +162,11 @@ size_t _printf_(3, 4) snprintf_safe(char *buf, size_t len, const char *fmt, ...) s8 nuke_whitespace(s8 z); +/* + * Returns: 0 on success, -1 on failure and sets errno + */ +int _nonnull_ createdir(char *dirpath); + /** * __attribute__((cleanup)) functions */ diff --git a/src/jppron.c b/src/jppron.c index c7b91ea..f668e67 100644 --- a/src/jppron.c +++ b/src/jppron.c @@ -325,21 +325,12 @@ static void add_from_index(database db, const char *index_path, s8 curdir) { json_close(s); } -/* - * Returns: 0 on success, -1 on failure and sets errno - */ -static int create_dir(char *dir_path) { - // TODO: Recursive implementation? - int status = mkdir(dir_path, S_IRWXU | S_IRWXG | S_IXOTH); - return (status == 0 || errno == EEXIST) ? 0 : -1; -} - static void jppron_create(char *audio_dir_path, s8 dbpth) { s8 dbfile = buildpath(dbpth, S("data.mdb")); remove((char *)dbfile.s); frees8(&dbfile); - int stat = create_dir((char *)dbpth.s); + int stat = createdir((char *)dbpth.s); die_on(stat != 0, "Creating directory '%s': %s", dbpth.s, strerror(errno)); _drop_(closedir) DIR *audio_dir = opendir(audio_dir_path); diff --git a/src/settings.c b/src/settings.c index 1636a37..0710389 100644 --- a/src/settings.c +++ b/src/settings.c @@ -1,8 +1,10 @@ +#include #include #include #include #include // getopt +#include #include #include "messages.h" @@ -252,24 +254,49 @@ static void read_pronunciation(GKeyFile *kf) { read_string(kf, "Pronunciation", "FolderPath", &cfg.pron.dirPath); } +static void copy_ready_callback(GObject *source_object, GAsyncResult *res, gpointer data) { + GError *error = NULL; + g_file_copy_finish(G_FILE(source_object), res, &error); + + if (error) + dbg("Error copying default config file: %s", error->message); + else + dbg("Successfully copied default config file to ~/.config/dictpopup/config.ini."); +} + +static void copy_default_config(char *cfgpth) { + // TODO: Make this OS independent + const char *default_config_location = "/usr/local/share/dictpopup/config.ini"; + _drop_(frees8) s8 config_dir = + buildpath(fromcstr_((char *)g_get_user_config_dir()), S("dictpopup")); + + int status = createdir((char *)config_dir.s); + if (status != 0) { + dbg("Could not create config directory '%s': %s", (char *)config_dir.s, strerror(errno)); + return; + } + + GFile *source = g_file_new_for_path(default_config_location); + GFile *dest = g_file_new_for_path(cfgpth); + g_file_copy_async(source, dest, G_FILE_COPY_NONE, G_PRIORITY_LOW, NULL, NULL, NULL, + copy_ready_callback, NULL); +} + void read_user_settings(int fieldmapping_max) { cfg = get_default_cfg(); // TODO: Put this to the end and only set missing values g_autoptr(GKeyFile) kf = g_key_file_new(); - GError *error = NULL; + g_autoptr(GError) error = NULL; _drop_(frees8) s8 cfgpth = buildpath(fromcstr_((char *)g_get_user_config_dir()), S("dictpopup"), S("config.ini")); if (!g_key_file_load_from_file(kf, (char *)cfgpth.s, G_KEY_FILE_NONE, &error)) { if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) - err("Could not find a config file in: \"%s\". Falling back to " - "default config.", - cfgpth.s); + err("Could not find a config file in: \"%s\". Copying default config.. ", cfgpth.s); else err("Error opening \"%s\": %s. Falling back to default config.", cfgpth.s, error->message); - g_error_free(error); - error = NULL; + copy_default_config((char *)cfgpth.s); } else { read_general(kf); read_anki(kf); diff --git a/src/util.c b/src/util.c index 2d2bae6..c88fdc8 100644 --- a/src/util.c +++ b/src/util.c @@ -1,8 +1,10 @@ +#include #include #include #include #include #include +#include // mkdir #include "util.h" @@ -358,3 +360,9 @@ s8 nuke_whitespace(s8 z) { return fromcstr_((char *)z.s); } + +int createdir(char *dirpath) { + // TODO: Recursive implementation + int status = mkdir(dirpath, S_IRWXU | S_IRWXG | S_IXOTH); + return (status == 0 || errno == EEXIST) ? 0 : -1; +}