diff --git a/lib/cfg-funcs.h b/lib/cfg-funcs.h index 283df3c7..9b218c31 100644 --- a/lib/cfg-funcs.h +++ b/lib/cfg-funcs.h @@ -125,25 +125,36 @@ bool rm_cfg_prepend_json( } return false; } +#define PREPEND_TO(list) \ + rm_path_prepend( \ + &(list), \ + real_path, \ + index, \ + preferred \ + ) + static INLINE bool rm_cfg_prepend_path( RmCfg *const cfg, const char *const path, + const unsigned int index, + const bool replay, const bool preferred ) { g_assert(cfg); char *real_path; if(rm_path_is_valid(path, &real_path)) { - rm_path_prepend( - (cfg->replay && rm_path_is_json(path)) ? - &cfg->json_paths : &cfg->paths, - real_path, - cfg->path_count++, - preferred - ); return true; + if(replay && rm_path_is_json(path)) { + PREPEND_TO(cfg->json_paths); + } else { + PREPEND_TO(cfg->paths); + ++(cfg->path_count); + } return true; } return false; } +#undef PREPEND_TO + static INLINE void rm_cfg_free_paths(RmCfg *const cfg) { g_assert(cfg); diff --git a/lib/cfg.h b/lib/cfg.h index cb0e4909..63e2cd3e 100644 --- a/lib/cfg.h +++ b/lib/cfg.h @@ -73,7 +73,6 @@ typedef struct RmCfg { gboolean progress_enabled; gboolean list_mounts; gboolean replay; - gboolean read_stdin; gboolean read_stdin0; gboolean no_backup; @@ -101,16 +100,13 @@ typedef struct RmCfg { * * + To record a unique index for each path supplied by the * user; a path's index represents the number of paths that - * were already processed. This is always the case. + * were already processed. This is the case DURING the + * processing of user-input options (such as '--replay'). * - * + To provide quick access to the length of its associated - * RmCfg::paths list. This is only the case when NOT running - * in "--replay" mode; when running in "--replay" mode, it - * just represents the total number of paths that have been - * supplied by the user, i.e., the sums of the lengths of - * the associated lists RmCfg::{paths,json_paths}, which is - * not meant to be a useful number to know, and is simply a - * byproduct of calculating path indicies. + * + To provide quick access to the length of its associated + * RmCfg::paths list. This is the case AFTER the processing + * of user-input options (including during the processing of + * non-option paths from the command line or stdin). */ guint path_count; diff --git a/lib/cmdline.c b/lib/cmdline.c index f457e7e1..56d07a8e 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -360,31 +360,6 @@ static GLogLevelFlags VERBOSITY_TO_LOG_LEVEL[] = {[0] = G_LOG_LEVEL_CRITICAL, [3] = G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO, [4] = G_LOG_LEVEL_DEBUG}; -static bool rm_cmd_read_paths_from_stdin(RmSession *session, bool is_prefd, - bool null_separated) { - char delim = null_separated ? 0 : '\n'; - - size_t buf_len = PATH_MAX; - char *path_buf = malloc(buf_len * sizeof(char)); - - bool all_paths_read = true; - - int path_len; - - /* Still read all paths on errors, so the user knows all paths that failed */ - while((path_len = getdelim(&path_buf, &buf_len, delim, stdin)) >= 0) { - if(path_len > 0) { - /* replace returned delimiter with null */ - if (path_buf[path_len - 1] == delim) { - path_buf[path_len - 1] = 0; - } - all_paths_read &= rm_cfg_prepend_path(session->cfg, path_buf, is_prefd); - } - } - - free(path_buf); - return all_paths_read; -} static bool rm_cmd_parse_output_pair(RmSession *session, const char *pair, GError **error) { @@ -1170,42 +1145,130 @@ static bool rm_cmd_set_cmdline(RmCfg *cfg, int argc, char **argv) { return true; } -static bool rm_cmd_set_paths(RmSession *session, char **paths) { - bool is_prefd = false; - bool all_paths_valid = true; - bool stdin_paths_preferred = false; - - RmCfg *cfg = session->cfg; - - /* Check the directory to be valid */ - for(int i = 0; paths && paths[i]; ++i) { - if(strcmp(paths[i], "-") == 0) { - cfg->read_stdin = true; +typedef struct rm_cmd_set_paths_vars { + RmCfg *const cfg; + char **const paths; + unsigned int index; + bool is_prefd; + bool read_stdin; + bool stdin_paths_preferred; + const bool null_separated; + bool all_paths_valid; +} rm_cmd_set_paths_vars; + +static INLINE +void rm_cmd_set_paths_from_cmdline( + rm_cmd_set_paths_vars *const v, + const bool replay +) { + g_assert(v); + g_assert(v->paths); + + for(char *path, **list = v->paths; (path = *list); ++list) { + if(path[0] == '-' && path[1] == 0) { + v->read_stdin = true; /* remember whether to treat stdin paths as preferred paths */ - stdin_paths_preferred = is_prefd; - } else if(strcmp(paths[i], "//") == 0) { + v->stdin_paths_preferred = v->is_prefd; + } else if(path[0] == '/' && path[1] == '/' && path[2] == 0) { /* the '//' separator separates non-preferred paths from preferred */ - is_prefd = !is_prefd; + v->is_prefd = !v->is_prefd; } else { - all_paths_valid &= rm_cfg_prepend_path(cfg, paths[i], is_prefd); + v->all_paths_valid &= rm_cfg_prepend_path( + v->cfg, path, v->index++, replay, v->is_prefd + ); + } + g_free(path); + } + g_free(v->paths); +} + +static INLINE +bool rm_cmd_set_paths_from_stdin( + rm_cmd_set_paths_vars *const v, + const bool replay +) { + g_assert(v); + g_assert(v->cfg); + + RmCfg *const cfg = v->cfg; + const bool is_prefd = v->stdin_paths_preferred; + + char delim = v->null_separated ? 0 : '\n'; + + size_t buf_len; + char *path_buf = malloc(buf_len = PATH_MAX); + if(!path_buf) { + rm_log_perror(_("Failed to allocate memory")); + return false; + } + + int path_len; + + /* Still read all paths on errors, so the user knows all paths that failed */ + while((path_len = getdelim(&path_buf, &buf_len, delim, stdin)) >= 0) { + if(path_len > 0) { + /* replace returned delimiter with null */ + if(path_buf[path_len - 1] == delim) { + path_buf[path_len - 1] = 0; + } + v->all_paths_valid &= rm_cfg_prepend_path( + cfg, path_buf, v->index++, replay, is_prefd + ); } } - g_strfreev(paths); + if(ferror(stdin)) { + rm_log_perror(_("Failed to read stdin")) + return false; + } + + free(path_buf); + return true; +} + +#define PROCESS_PATHS(replay) \ + if(paths) { \ + rm_cmd_set_paths_from_cmdline(&v, (replay)); \ + } \ + if(v.read_stdin) { \ + if(!rm_cmd_set_paths_from_stdin(&v, (replay))) { \ + rm_log_error_line(_("Could not process path arguments")); \ + return false; \ + } \ + } + +static INLINE +bool rm_cmd_set_paths(RmCfg *const cfg, char **const paths) { + g_assert(cfg); + + const bool replay = cfg->replay; + const bool read_stdin0 = cfg->read_stdin0; + rm_cmd_set_paths_vars v = { + .cfg = cfg, + .paths = paths, + .index = cfg->path_count, + .read_stdin = read_stdin0, + .null_separated = read_stdin0, + .all_paths_valid = true + }; + + cfg->path_count = 0; - if(cfg->read_stdin || cfg->read_stdin0) { - /* option '-' means read paths from stdin */ - all_paths_valid &= - rm_cmd_read_paths_from_stdin(session, stdin_paths_preferred, cfg->read_stdin0); + if(replay) { + PROCESS_PATHS(true); + } else { + PROCESS_PATHS(false); } - if(g_slist_length(cfg->paths) == 0 && all_paths_valid) { + if(cfg->path_count == 0 && v.all_paths_valid) { /* Still no path set? - use `pwd` */ - rm_cfg_prepend_path(session->cfg, cfg->iwd, is_prefd); + rm_cfg_prepend_path( + cfg, cfg->iwd, v.index, /* replay */ false, v.is_prefd + ); } /* Only return success if everything is fine. */ - return all_paths_valid; + return v.all_paths_valid; } static bool rm_cmd_set_outputs(RmSession *session, GError **error) { @@ -1466,7 +1529,7 @@ bool rm_cmd_parse_args(int argc, char **argv, RmSession *session) { goto cleanup; } - if(!rm_cmd_set_paths(session, paths)) { + if(!rm_cmd_set_paths(cfg, paths)) { error = g_error_new(RM_ERROR_QUARK, 0, _("Not all given paths are valid. Aborting")); goto cleanup; } diff --git a/lib/treemerge.c b/lib/treemerge.c index ab0bd7f9..282a3462 100644 --- a/lib/treemerge.c +++ b/lib/treemerge.c @@ -189,7 +189,7 @@ static bool rm_tm_count_files(RmTrie *count_tree, const RmCfg *const cfg) { const char **const path_vec = malloc(sizeof(*path_vec) * (path_count + 1)); if(!path_vec) { - rm_log_error(_("Failed to allocate memory. Out of memory?")); + rm_log_perror(_("Failed to allocate memory")); return false; } diff --git a/po/de.po b/po/de.po index ac64b56a..feb59eb5 100644 --- a/po/de.po +++ b/po/de.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: rmlint 2.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-06 00:43+0000\n" +"POT-Creation-Date: 2018-10-15 04:46+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1015,8 +1015,8 @@ msgstr "" msgid "Failed to complete setup for merging directories" msgstr "" -#: lib/treemerge.c -msgid "Failed to allocate memory. Out of memory?" +#: lib/treemerge.c lib/cmdline.c +msgid "Failed to allocate memory" msgstr "" #: lib/cmdline.c @@ -1038,6 +1038,14 @@ msgstr "" msgid "Could not get metadata for path \"%s\": %s" msgstr "" +#: lib/cmdline.c +msgid "Failed to read stdin" +msgstr "" + +#: lib/cmdline.c +msgid "Could not process path arguments" +msgstr "" + #~ msgid "%s%15" #~ msgstr "%s%15" diff --git a/po/es.po b/po/es.po index f24d92bb..d0a4c46e 100644 --- a/po/es.po +++ b/po/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: rmlint 2.4.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-06 00:43+0000\n" +"POT-Creation-Date: 2018-10-15 04:46+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -992,8 +992,8 @@ msgstr "" msgid "Failed to complete setup for merging directories" msgstr "" -#: lib/treemerge.c -msgid "Failed to allocate memory. Out of memory?" +#: lib/treemerge.c lib/cmdline.c +msgid "Failed to allocate memory" msgstr "" #: lib/cmdline.c @@ -1015,6 +1015,14 @@ msgstr "" msgid "Could not get metadata for path \"%s\": %s" msgstr "" +#: lib/cmdline.c +msgid "Failed to read stdin" +msgstr "" + +#: lib/cmdline.c +msgid "Could not process path arguments" +msgstr "" + #~ msgid "caching is not supported due to missing json-glib library." #~ msgstr "" #~ "el cacheo no es soportado debido a la librería inexistente json-glib" diff --git a/po/fr.po b/po/fr.po index 5dcbdc80..2b2c58c1 100644 --- a/po/fr.po +++ b/po/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: rmlint 2.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-06 00:43+0000\n" +"POT-Creation-Date: 2018-10-15 04:46+0000\n" "PO-Revision-Date: 2014-12-02 13:37+0100\n" "Last-Translator: F. \n" "Language-Team: none\n" @@ -988,8 +988,8 @@ msgstr "" msgid "Failed to complete setup for merging directories" msgstr "" -#: lib/treemerge.c -msgid "Failed to allocate memory. Out of memory?" +#: lib/treemerge.c lib/cmdline.c +msgid "Failed to allocate memory" msgstr "" #: lib/cmdline.c @@ -1011,6 +1011,14 @@ msgstr "" msgid "Could not get metadata for path \"%s\": %s" msgstr "" +#: lib/cmdline.c +msgid "Failed to read stdin" +msgstr "" + +#: lib/cmdline.c +msgid "Could not process path arguments" +msgstr "" + #~ msgid "caching is not supported due to missing json-glib library." #~ msgstr "Cache non supporté, librairie json-glib manquante." diff --git a/po/rmlint.pot b/po/rmlint.pot index 7e3e1ce4..94b92658 100644 --- a/po/rmlint.pot +++ b/po/rmlint.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: rmlint 2.6.2\n" +"Project-Id-Version: rmlint 2.7.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-10-06 00:43+0000\n" +"POT-Creation-Date: 2018-10-15 04:46+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -937,8 +937,8 @@ msgstr "" msgid "Failed to complete setup for merging directories" msgstr "" -#: lib/treemerge.c -msgid "Failed to allocate memory. Out of memory?" +#: lib/treemerge.c lib/cmdline.c +msgid "Failed to allocate memory" msgstr "" #: lib/cmdline.c @@ -959,3 +959,11 @@ msgstr "" #, c-format msgid "Could not get metadata for path \"%s\": %s" msgstr "" + +#: lib/cmdline.c +msgid "Failed to read stdin" +msgstr "" + +#: lib/cmdline.c +msgid "Could not process path arguments" +msgstr ""