|
|
771b4bc |
From 3e37501e12297f2ddd02d5cabb056166470c783a Mon Sep 17 00:00:00 2001
|
|
|
771b4bc |
From: Gergely Nagy <algernon@balabit.hu>
|
|
|
771b4bc |
Date: Wed, 16 May 2012 18:11:27 +0200
|
|
|
771b4bc |
Subject: [PATCH] delta: Support filtering what type of deltas to show
|
|
|
771b4bc |
|
|
|
771b4bc |
Not everyone is interested in every kind of deltas (and some might
|
|
|
771b4bc |
even be interested knowing which files do not have overrides), so this
|
|
|
771b4bc |
here is an implementation of a --type=LIST... option for
|
|
|
771b4bc |
systemd-delta, that makes it possible to filter what subset of deltas
|
|
|
771b4bc |
we want.
|
|
|
771b4bc |
|
|
|
771b4bc |
The available modifiers are masked, equivalent, redirected, overriden,
|
|
|
771b4bc |
and unchanged - they should be self explanatory, and the man page
|
|
|
771b4bc |
explains them in a little more detail anyway.
|
|
|
771b4bc |
|
|
|
771b4bc |
As a side effect, in case of overriden files, the diff output was made
|
|
|
771b4bc |
optional.
|
|
|
771b4bc |
|
|
|
771b4bc |
By default, everything is shown (with a diff, if appropriate) except
|
|
|
771b4bc |
for completely unchanged files.
|
|
|
771b4bc |
|
|
|
771b4bc |
Signed-off-by: Gergely Nagy <algernon@balabit.hu>
|
|
|
771b4bc |
(cherry picked from commit 807f46452202891731b2317ef9bc9a6bc7115f23)
|
|
|
771b4bc |
---
|
|
|
771b4bc |
man/systemd-delta.xml | 60 +++++++++++++++++++++
|
|
|
771b4bc |
src/delta/delta.c | 139 +++++++++++++++++++++++++++++++++++++++++++------
|
|
|
771b4bc |
2 files changed, 183 insertions(+), 16 deletions(-)
|
|
|
771b4bc |
|
|
|
771b4bc |
diff --git a/man/systemd-delta.xml b/man/systemd-delta.xml
|
|
|
771b4bc |
index 0e06b48..03c7178 100644
|
|
|
771b4bc |
--- a/man/systemd-delta.xml
|
|
|
771b4bc |
+++ b/man/systemd-delta.xml
|
|
|
771b4bc |
@@ -99,6 +99,66 @@
|
|
|
771b4bc |
pager.</para></listitem>
|
|
|
771b4bc |
</varlistentry>
|
|
|
771b4bc |
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><option>--type=</option></term>
|
|
|
771b4bc |
+ <term><option>-t</option></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>When listing the
|
|
|
771b4bc |
+ differences, only list those that are
|
|
|
771b4bc |
+ asked for. The list itself is a
|
|
|
771b4bc |
+ comma-separated list of desired
|
|
|
771b4bc |
+ difference types.</para>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <para>Recognised types are:
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <variablelist>
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><varname>masked</varname></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>Show masked files</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><varname>equivalent</varname></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>Show overriden
|
|
|
771b4bc |
+ files that while overriden, do
|
|
|
771b4bc |
+ not differ in content.</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><varname>redirected</varname></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>Show files that
|
|
|
771b4bc |
+ are redirected to another.</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><varname>overriden</varname></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>Show overriden,
|
|
|
771b4bc |
+ and changed files.</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><varname>unchanged</varname></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>Show unmodified
|
|
|
771b4bc |
+ files too.</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+ </variablelist>
|
|
|
771b4bc |
+ </para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <varlistentry>
|
|
|
771b4bc |
+ <term><option>--diff=</option></term>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ <listitem><para>When showing modified
|
|
|
771b4bc |
+ files, when a file is overriden show a
|
|
|
771b4bc |
+ diff aswell. This option takes a
|
|
|
771b4bc |
+ boolean argument.</para></listitem>
|
|
|
771b4bc |
+ </varlistentry>
|
|
|
771b4bc |
+
|
|
|
771b4bc |
</variablelist>
|
|
|
771b4bc |
|
|
|
771b4bc |
</refsect1>
|
|
|
771b4bc |
diff --git a/src/delta/delta.c b/src/delta/delta.c
|
|
|
771b4bc |
index 2e33759..585bb0c 100644
|
|
|
771b4bc |
--- a/src/delta/delta.c
|
|
|
771b4bc |
+++ b/src/delta/delta.c
|
|
|
771b4bc |
@@ -55,7 +55,57 @@ static int equivalent(const char *a, const char *b) {
|
|
|
771b4bc |
return r;
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
-static int found_override(const char *top, const char *bottom) {
|
|
|
771b4bc |
+#define SHOW_MASKED 1 << 0
|
|
|
771b4bc |
+#define SHOW_EQUIV 1 << 1
|
|
|
771b4bc |
+#define SHOW_REDIR 1 << 2
|
|
|
771b4bc |
+#define SHOW_OVERRIDEN 1 << 3
|
|
|
771b4bc |
+#define SHOW_UNCHANGED 1 << 4
|
|
|
771b4bc |
+#define SHOW_DIFF 1 << 5
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+#define SHOW_DEFAULTS \
|
|
|
771b4bc |
+ (SHOW_MASKED | SHOW_EQUIV | SHOW_REDIR | SHOW_OVERRIDEN | SHOW_DIFF)
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int notify_override_masked(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
+ if (!(flags & SHOW_MASKED))
|
|
|
771b4bc |
+ return 0;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ printf(ANSI_HIGHLIGHT_RED_ON "[MASK]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ return 1;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int notify_override_equiv(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
+ if (!(flags & SHOW_EQUIV))
|
|
|
771b4bc |
+ return 0;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ printf(ANSI_HIGHLIGHT_GREEN_ON "[EQUIVALENT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ return 1;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int notify_override_redir(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
+ if (!(flags & SHOW_REDIR))
|
|
|
771b4bc |
+ return 0;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ printf(ANSI_HIGHLIGHT_ON "[REDIRECT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ return 1;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int notify_override_overriden(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
+ if (!(flags & SHOW_OVERRIDEN))
|
|
|
771b4bc |
+ return 0;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ printf(ANSI_HIGHLIGHT_ON "[OVERRIDE]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ return 1;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int notify_override_unchanged(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
+ if (!(flags & SHOW_UNCHANGED))
|
|
|
771b4bc |
+ return 0;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ printf(ANSI_HIGHLIGHT_ON "[UNCHANGED]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ return 1;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int found_override(int flags, const char *top, const char *bottom) {
|
|
|
771b4bc |
char *dest;
|
|
|
771b4bc |
int k;
|
|
|
771b4bc |
pid_t pid;
|
|
|
771b4bc |
@@ -64,22 +114,24 @@ static int found_override(const char *top, const char *bottom) {
|
|
|
771b4bc |
assert(bottom);
|
|
|
771b4bc |
|
|
|
771b4bc |
if (null_or_empty_path(top) > 0) {
|
|
|
771b4bc |
- printf(ANSI_HIGHLIGHT_RED_ON "[MASK]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ notify_override_masked(flags, top, bottom);
|
|
|
771b4bc |
goto finish;
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
k = readlink_malloc(top, &dest);
|
|
|
771b4bc |
if (k >= 0) {
|
|
|
771b4bc |
if (equivalent(dest, bottom) > 0)
|
|
|
771b4bc |
- printf(ANSI_HIGHLIGHT_GREEN_ON "[EQUIVALENT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ notify_override_equiv(flags, top, bottom);
|
|
|
771b4bc |
else
|
|
|
771b4bc |
- printf(ANSI_HIGHLIGHT_ON "[REDIRECT]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ notify_override_redir(flags, top, bottom);
|
|
|
771b4bc |
|
|
|
771b4bc |
free(dest);
|
|
|
771b4bc |
goto finish;
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
- printf(ANSI_HIGHLIGHT_ON "[OVERRIDE]" ANSI_HIGHLIGHT_OFF " %s → %s\n", top, bottom);
|
|
|
771b4bc |
+ notify_override_overriden(flags, top, bottom);
|
|
|
771b4bc |
+ if (!(flags & SHOW_DIFF))
|
|
|
771b4bc |
+ goto finish;
|
|
|
771b4bc |
|
|
|
771b4bc |
putchar('\n');
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -174,7 +226,7 @@ finish:
|
|
|
771b4bc |
return r;
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
-static int process_suffix(const char *prefixes, const char *suffix) {
|
|
|
771b4bc |
+static int process_suffix(int flags, const char *prefixes, const char *suffix) {
|
|
|
771b4bc |
const char *p;
|
|
|
771b4bc |
char *f;
|
|
|
771b4bc |
Hashmap *top, *bottom;
|
|
|
771b4bc |
@@ -220,10 +272,12 @@ static int process_suffix(const char *prefixes, const char *suffix) {
|
|
|
771b4bc |
o = hashmap_get(bottom, path_get_file_name(f));
|
|
|
771b4bc |
assert(o);
|
|
|
771b4bc |
|
|
|
771b4bc |
- if (path_equal(o, f))
|
|
|
771b4bc |
+ if (path_equal(o, f)) {
|
|
|
771b4bc |
+ notify_override_unchanged(flags, f, o);
|
|
|
771b4bc |
continue;
|
|
|
771b4bc |
+ }
|
|
|
771b4bc |
|
|
|
771b4bc |
- k = found_override(f, o);
|
|
|
771b4bc |
+ k = found_override(flags, f, o);
|
|
|
771b4bc |
if (k < 0)
|
|
|
771b4bc |
r = k;
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -239,21 +293,21 @@ finish:
|
|
|
771b4bc |
return r < 0 ? r : n_found;
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
-static int process_suffix_chop(const char *prefixes, const char *suffix) {
|
|
|
771b4bc |
+static int process_suffix_chop(int flags, const char *prefixes, const char *suffix) {
|
|
|
771b4bc |
const char *p;
|
|
|
771b4bc |
|
|
|
771b4bc |
assert(prefixes);
|
|
|
771b4bc |
assert(suffix);
|
|
|
771b4bc |
|
|
|
771b4bc |
if (!path_is_absolute(suffix))
|
|
|
771b4bc |
- return process_suffix(prefixes, suffix);
|
|
|
771b4bc |
+ return process_suffix(flags, prefixes, suffix);
|
|
|
771b4bc |
|
|
|
771b4bc |
/* Strip prefix from the suffix */
|
|
|
771b4bc |
NULSTR_FOREACH(p, prefixes) {
|
|
|
771b4bc |
if (startswith(suffix, p)) {
|
|
|
771b4bc |
suffix += strlen(p);;
|
|
|
771b4bc |
suffix += strspn(suffix, "/");
|
|
|
771b4bc |
- return process_suffix(prefixes, suffix);
|
|
|
771b4bc |
+ return process_suffix(flags, prefixes, suffix);
|
|
|
771b4bc |
}
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -267,14 +321,42 @@ static void help(void) {
|
|
|
771b4bc |
"Find overridden configuration files.\n\n"
|
|
|
771b4bc |
" -h --help Show this help\n"
|
|
|
771b4bc |
" --version Show package version\n"
|
|
|
771b4bc |
- " --no-pager Do not pipe output into a pager\n",
|
|
|
771b4bc |
+ " --no-pager Do not pipe output into a pager\n"
|
|
|
771b4bc |
+ " --diff[=1|0] Show a diff when overriden files differ\n"
|
|
|
771b4bc |
+ " -t --type=LIST... Only display a selected set of override types\n",
|
|
|
771b4bc |
program_invocation_short_name);
|
|
|
771b4bc |
}
|
|
|
771b4bc |
|
|
|
771b4bc |
-static int parse_argv(int argc, char *argv[]) {
|
|
|
771b4bc |
+static int parse_flags(int flags, const char *flag_str) {
|
|
|
771b4bc |
+ char *w, *state;
|
|
|
771b4bc |
+ size_t l;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ FOREACH_WORD(w, l, flag_str, state) {
|
|
|
771b4bc |
+ if (strncmp("masked", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_MASKED;
|
|
|
771b4bc |
+ } else if (strncmp ("equivalent", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_EQUIV;
|
|
|
771b4bc |
+ } else if (strncmp("redirected", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_REDIR;
|
|
|
771b4bc |
+ } else if (strncmp("override", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_OVERRIDEN;
|
|
|
771b4bc |
+ } else if (strncmp("unchanged", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_UNCHANGED;
|
|
|
771b4bc |
+ } else if (strncmp("default", w, l) == 0) {
|
|
|
771b4bc |
+ flags |= SHOW_DEFAULTS;
|
|
|
771b4bc |
+ } else {
|
|
|
771b4bc |
+ log_error("Unknown type filter: %s", w);
|
|
|
771b4bc |
+ return -1;
|
|
|
771b4bc |
+ }
|
|
|
771b4bc |
+ }
|
|
|
771b4bc |
+ return flags;
|
|
|
771b4bc |
+}
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+static int parse_argv(int argc, char *argv[], int *flags) {
|
|
|
771b4bc |
|
|
|
771b4bc |
enum {
|
|
|
771b4bc |
ARG_NO_PAGER = 0x100,
|
|
|
771b4bc |
+ ARG_DIFF,
|
|
|
771b4bc |
ARG_VERSION
|
|
|
771b4bc |
};
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -282,6 +364,8 @@ static int parse_argv(int argc, char *argv[]) {
|
|
|
771b4bc |
{ "help", no_argument, NULL, 'h' },
|
|
|
771b4bc |
{ "version", no_argument, NULL, ARG_VERSION },
|
|
|
771b4bc |
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
|
|
771b4bc |
+ { "diff", optional_argument, NULL, ARG_DIFF },
|
|
|
771b4bc |
+ { "type", required_argument, NULL, 't' },
|
|
|
771b4bc |
{ NULL, 0, NULL, 0 }
|
|
|
771b4bc |
};
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -311,6 +395,23 @@ static int parse_argv(int argc, char *argv[]) {
|
|
|
771b4bc |
case '?':
|
|
|
771b4bc |
return -EINVAL;
|
|
|
771b4bc |
|
|
|
771b4bc |
+ case 't':
|
|
|
771b4bc |
+ *flags = parse_flags(*flags, optarg);
|
|
|
771b4bc |
+ if (*flags < 0)
|
|
|
771b4bc |
+ return -EINVAL;
|
|
|
771b4bc |
+ break;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
+ case ARG_DIFF:
|
|
|
771b4bc |
+ if (!optarg) {
|
|
|
771b4bc |
+ *flags |= SHOW_DIFF;
|
|
|
771b4bc |
+ } else {
|
|
|
771b4bc |
+ if (parse_boolean(optarg))
|
|
|
771b4bc |
+ *flags |= SHOW_DIFF;
|
|
|
771b4bc |
+ else
|
|
|
771b4bc |
+ *flags &= ~SHOW_DIFF;
|
|
|
771b4bc |
+ }
|
|
|
771b4bc |
+ break;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
default:
|
|
|
771b4bc |
log_error("Unknown option code %c", c);
|
|
|
771b4bc |
return -EINVAL;
|
|
|
771b4bc |
@@ -348,14 +449,20 @@ int main(int argc, char *argv[]) {
|
|
|
771b4bc |
|
|
|
771b4bc |
int r = 0, k;
|
|
|
771b4bc |
int n_found = 0;
|
|
|
771b4bc |
+ int flags = 0;
|
|
|
771b4bc |
|
|
|
771b4bc |
log_parse_environment();
|
|
|
771b4bc |
log_open();
|
|
|
771b4bc |
|
|
|
771b4bc |
- r = parse_argv(argc, argv);
|
|
|
771b4bc |
+ r = parse_argv(argc, argv, &flags);
|
|
|
771b4bc |
if (r <= 0)
|
|
|
771b4bc |
goto finish;
|
|
|
771b4bc |
|
|
|
771b4bc |
+ if (flags == 0)
|
|
|
771b4bc |
+ flags = SHOW_DEFAULTS;
|
|
|
771b4bc |
+ if (flags == SHOW_DIFF)
|
|
|
771b4bc |
+ flags |= SHOW_OVERRIDEN;
|
|
|
771b4bc |
+
|
|
|
771b4bc |
if (!arg_no_pager)
|
|
|
771b4bc |
pager_open();
|
|
|
771b4bc |
|
|
|
771b4bc |
@@ -363,7 +470,7 @@ int main(int argc, char *argv[]) {
|
|
|
771b4bc |
int i;
|
|
|
771b4bc |
|
|
|
771b4bc |
for (i = optind; i < argc; i++) {
|
|
|
771b4bc |
- k = process_suffix_chop(prefixes, argv[i]);
|
|
|
771b4bc |
+ k = process_suffix_chop(flags, prefixes, argv[i]);
|
|
|
771b4bc |
if (k < 0)
|
|
|
771b4bc |
r = k;
|
|
|
771b4bc |
else
|
|
|
771b4bc |
@@ -374,7 +481,7 @@ int main(int argc, char *argv[]) {
|
|
|
771b4bc |
const char *n;
|
|
|
771b4bc |
|
|
|
771b4bc |
NULSTR_FOREACH(n, suffixes) {
|
|
|
771b4bc |
- k = process_suffix(prefixes, n);
|
|
|
771b4bc |
+ k = process_suffix(flags, prefixes, n);
|
|
|
771b4bc |
if (k < 0)
|
|
|
771b4bc |
r = k;
|
|
|
771b4bc |
else
|