This is a rework of the previous patch which adds:
- an aug_transform API call
- a transform command for aug_srun
- a -t|--transform option to augtool
This is the second version, with the following changes:
- rebased on master;
- augeas.c, augtool.c: do not use malloc(), use xasprintf() and catch errors;
- augtool.c: move all transforms to add_transforms();
- change syntax of --transform|-t to make aug_srun syntax.
---
src/augeas.c | 62 +++++++++++++++++++++++++++++
src/augeas.h | 14 +++++++
src/augeas_sym.version | 1 +
src/augrun.c | 46 +++++++++++++++++++++
src/augtool.c | 104 +++++++++++++++++++++++++++++++++---------------
tests/run.tests | 23 +++++++++++
tests/test-api.c | 46 +++++++++++++++++++++
7 files changed, 263 insertions(+), 33 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index a2ffa03..8ad1a91 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -1761,6 +1761,68 @@ int aug_to_xml(const struct augeas *aug, const char
*pathin,
return -1;
}
+int aug_transform(struct augeas *aug, const char *lens, const char *file, int
excl) {
+ int r = 0;
+ char *filter;
+ char *lenspath;
+ char *inclpath;
+ char *lenslenspath;
+ char *lensname = NULL;
+
+ api_entry(aug);
+
+ ARG_CHECK(STREQ("", lens), aug, "aug_transform: LENS must not be empty");
+ ARG_CHECK(STREQ("", file), aug, "aug_transform: FILE must not be empty");
+
+ r = ALLOC_N(filter, 5);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+ if (excl)
+ strcpy(filter, "excl");
+ else
+ strcpy(filter, "incl");
+
+ r = xasprintf(&lenspath, "/augeas/load/%s", lens);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+
+ r = xasprintf(&inclpath, "%s/%s[. = '%s']", lenspath, filter, file);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+
+ r = xasprintf(&lenslenspath, "%s/lens", lenspath);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+
+ if (strchr(lens, '.')) {
+ r = xasprintf(&lensname, "%s", lensname);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+ } else {
+ r = xasprintf(&lensname, "%s.lns", lens);
+ ERR_THROW(r < 0, aug, AUG_ENOMEM, NULL);
+ }
+
+ if (aug_match(aug, lenslenspath, NULL) == 0)
+ r = aug_set(aug, lenslenspath, lensname);
+ ERR_BAIL(aug);
+
+ r = aug_set(aug, inclpath, file);
+ ERR_BAIL(aug);
+
+ free(filter);
+ free(lenspath);
+ free(inclpath);
+ free(lenslenspath);
+ free(lensname);
+ api_exit(aug);
+
+ return r;
+ error:
+ free(filter);
+ free(lenspath);
+ free(inclpath);
+ free(lenslenspath);
+ free(lensname);
+ api_exit(aug);
+ return -1;
+}
+
int aug_print(const struct augeas *aug, FILE *out, const char *pathin) {
struct pathx *p;
int result;
diff --git a/src/augeas.h b/src/augeas.h
index 7f7ac14..00e4c9f 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -362,6 +362,20 @@ int aug_to_xml(const augeas *aug, const char *path,
xmlNode **xmldoc,
unsigned int flags);
/*
+ * Function: aug_transform
+ *
+ * Add a transform for FILE using LENS.
+ * EXCL specifies if this the file is to be included (0)
+ * or excluded (1) from the LENS.
+ * The LENS maybe be a module name or a full lens name.
+ * If a module name is given, then lns will be the lens assumed.
+ *
+ * Returns:
+ * 1 on success, -1 on failure
+ */
+int aug_transform(augeas *aug, const char *lens, const char *file, int excl);
+
+/*
* Function: aug_srun
*
* Run one or more newline-separated commands. The output of the commands
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index eb53941..c56d443 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -57,4 +57,5 @@ AUGEAS_0.16.0 {
aug_text_store;
aug_text_retrieve;
aug_rename;
+ aug_transform;
} AUGEAS_0.15.0;
diff --git a/src/augrun.c b/src/augrun.c
index 78ef414..58c9100 100644
--- a/src/augrun.c
+++ b/src/augrun.c
@@ -942,6 +942,51 @@ static const struct command_def cmd_dump_xml_def = {
.help = "Export entries in the tree as XML. If PATH is given, printing
starts there,\n otherwise the whole tree is printed. If FILENAME is given, the
XML is saved\n to the given file."
};
+static void cmd_transform(struct command *cmd) {
+ const char *lens = arg_value(cmd, "lens");
+ const char *filter = arg_value(cmd, "filter");
+ const char *file = arg_value(cmd, "file");
+ int r, excl = 0;
+
+ if (STREQ("excl", filter))
+ excl = 1;
+ else if (STREQ("incl", filter))
+ excl = 0;
+ else
+ ERR_REPORT(cmd, AUG_ECMDRUN,
+ "FILTER must be \"incl\" or \"excl\"");
+
+ r = aug_transform(cmd->aug, lens, file, excl);
+ if (r < 0)
+ ERR_REPORT(cmd, AUG_ECMDRUN,
+ "Adding transform for %s on lens %s failed", lens, file);
+}
+
+static const struct command_opt_def cmd_transform_opts[] = {
+ { .type = CMD_PATH, .name = "lens", .optional = false,
+ .help = "the lens to use" },
+ { .type = CMD_PATH, .name = "filter", .optional = false,
+ .help = "the type of filter, either \"incl\" or \"excl\"" },
+ { .type = CMD_PATH, .name = "file", .optional = false,
+ .help = "the file to associate to the lens" },
+ CMD_OPT_DEF_LAST
+};
+
+static const char const cmd_transform_help[] =
+ "Add a transform for FILE using LENS. The LENS may be a module name or a\n"
+ " full lens name. If a module name is given, then \"lns\" will be the
lens\n"
+ " assumed. The FILTER must be either \"incl\" or \"excl\". If the filter
is\n"
+ " \"incl\", the FILE will be parsed by the LENS. If the filter is
\"excl\",\n"
+ " the FILE will be excluded from the LENS. FILE may contain wildcards." ;
+
+static const struct command_def cmd_transform_def = {
+ .name = "transform",
+ .opts = cmd_transform_opts,
+ .handler = cmd_transform,
+ .synopsis = "add a transform",
+ .help = cmd_transform_help
+};
+
static void cmd_save(struct command *cmd) {
int r;
r = aug_save(cmd->aug);
@@ -1132,6 +1177,7 @@ static const struct command_def const *commands[] = {
&cmd_store_def,
&cmd_retrieve_def,
&cmd_touch_def,
+ &cmd_transform_def,
&cmd_help_def,
&cmd_def_last
};
diff --git a/src/augtool.c b/src/augtool.c
index bb0becc..f2c2c92 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -44,6 +44,8 @@ static const char *const progname = "augtool";
static unsigned int flags = AUG_NONE;
const char *root = NULL;
char *loadpath = NULL;
+char *transforms = NULL;
+size_t transformslen = 0;
const char *inputfile = NULL;
int echo_commands = 0; /* Gets also changed in main_loop */
bool print_version = false;
@@ -168,7 +170,8 @@ static char *readline_command_generator(const char *text,
int state) {
"quit", "clear", "defnode", "defvar",
"get", "ins", "load", "ls", "match",
"mv", "rename", "print", "dump-xml", "rm", "save", "set", "setm",
- "clearm", "span", "store", "retrieve", "help", NULL };
+ "clearm", "span", "store", "retrieve", "transform",
+ "help", NULL };
static int current = 0;
const char *name;
@@ -266,22 +269,25 @@ static void usage(void) {
fprintf(stderr, "Run '%s help' to get a list of possible commands.\n",
progname);
fprintf(stderr, "\nOptions:\n\n");
- fprintf(stderr, " -c, --typecheck typecheck lenses\n");
- fprintf(stderr, " -b, --backup preserve originals of modified files
with\n"
- " extension '.augsave'\n");
- fprintf(stderr, " -n, --new save changes in files with extension
'.augnew',\n"
- " leave original unchanged\n");
- fprintf(stderr, " -r, --root ROOT use ROOT as the root of the
filesystem\n");
- fprintf(stderr, " -I, --include DIR search DIR for modules; can be given
mutiple times\n");
- fprintf(stderr, " -e, --echo echo commands when reading from a
file\n");
- fprintf(stderr, " -f, --file FILE read commands from FILE\n");
- fprintf(stderr, " -s, --autosave automatically save at the end of
instructions\n");
- fprintf(stderr, " -i, --interactive run an interactive shell after
evaluating the commands in STDIN and FILE\n");
- fprintf(stderr, " -S, --nostdinc do not search the builtin default
directories for modules\n");
- fprintf(stderr, " -L, --noload do not load any files into the tree
on startup\n");
- fprintf(stderr, " -A, --noautoload do not autoload modules from the
search path\n");
- fprintf(stderr, " --span load span positions for nodes
related to a file\n");
- fprintf(stderr, " --version print version information and
exit.\n");
+ fprintf(stderr, " -c, --typecheck typecheck lenses\n");
+ fprintf(stderr, " -b, --backup preserve originals of
modified files with\n"
+ " extension '.augsave'\n");
+ fprintf(stderr, " -n, --new save changes in files with
extension '.augnew',\n"
+ " leave original unchanged\n");
+ fprintf(stderr, " -r, --root ROOT use ROOT as the root of the
filesystem\n");
+ fprintf(stderr, " -I, --include DIR search DIR for modules; can
be given mutiple times\n");
+ fprintf(stderr, " -t, --transform LENS=FILE add a transform for FILE
using LENS\n");
+ fprintf(stderr, " -e, --echo echo commands when reading
from a file\n");
+ fprintf(stderr, " -f, --file FILE read commands from FILE\n");
+ fprintf(stderr, " -s, --autosave automatically save at the
end of instructions\n");
+ fprintf(stderr, " -i, --interactive run an interactive shell
after evaluating\n"
+ " the commands in STDIN and
FILE\n");
+ fprintf(stderr, " -S, --nostdinc do not search the builtin
default directories\n"
+ " for modules\n");
+ fprintf(stderr, " -L, --noload do not load any files into
the tree on startup\n");
+ fprintf(stderr, " -A, --noautoload do not autoload modules from
the search path\n");
+ fprintf(stderr, " --span load span positions for
nodes related to a file\n");
+ fprintf(stderr, " --version print version information
and exit.\n");
exit(EXIT_FAILURE);
}
@@ -294,26 +300,27 @@ static void parse_opts(int argc, char **argv) {
VAL_SPAN = VAL_VERSION + 1
};
struct option options[] = {
- { "help", 0, 0, 'h' },
- { "typecheck", 0, 0, 'c' },
- { "backup", 0, 0, 'b' },
- { "new", 0, 0, 'n' },
- { "root", 1, 0, 'r' },
- { "include", 1, 0, 'I' },
- { "echo", 0, 0, 'e' },
- { "file", 1, 0, 'f' },
- { "autosave", 0, 0, 's' },
- { "interactive", 0, 0, 'i' },
- { "nostdinc", 0, 0, 'S' },
- { "noload", 0, 0, 'L' },
- { "noautoload", 0, 0, 'A' },
- { "span", 0, 0, VAL_SPAN },
- { "version", 0, 0, VAL_VERSION },
+ { "help", 0, 0, 'h' },
+ { "typecheck", 0, 0, 'c' },
+ { "backup", 0, 0, 'b' },
+ { "new", 0, 0, 'n' },
+ { "root", 1, 0, 'r' },
+ { "include", 1, 0, 'I' },
+ { "transform", 1, 0, 't' },
+ { "echo", 0, 0, 'e' },
+ { "file", 1, 0, 'f' },
+ { "autosave", 0, 0, 's' },
+ { "interactive", 0, 0, 'i' },
+ { "nostdinc", 0, 0, 'S' },
+ { "noload", 0, 0, 'L' },
+ { "noautoload", 0, 0, 'A' },
+ { "span", 0, 0, VAL_SPAN },
+ { "version", 0, 0, VAL_VERSION },
{ 0, 0, 0, 0}
};
int idx;
- while ((opt = getopt_long(argc, argv, "hnbcr:I:ef:siSLA", options, &idx))
!= -1) {
+ while ((opt = getopt_long(argc, argv, "hnbcr:I:t:ef:siSLA", options,
&idx)) != -1) {
switch(opt) {
case 'c':
flags |= AUG_TYPE_CHECK;
@@ -333,6 +340,9 @@ static void parse_opts(int argc, char **argv) {
case 'I':
argz_add(&loadpath, &loadpathlen, optarg);
break;
+ case 't':
+ argz_add(&transforms, &transformslen, optarg);
+ break;
case 'e':
echo_commands = 1;
break;
@@ -537,6 +547,33 @@ static int run_args(int argc, char **argv) {
return (code == 0 || code == -2) ? 0 : -1;
}
+static void add_transforms(char *ts, size_t tslen) {
+ char *command;
+ int r;
+ char *t = NULL;
+ bool added_transform = false;
+
+ while ((t = argz_next(ts, tslen, t))) {
+ r = xasprintf(&command, "transform %s", t);
+ if (r < 0)
+ fprintf(stderr, "error: Failed to add transform %s: could not
allocate memory\n", t);
+
+ r = aug_srun(aug, stdout, command);
+ if (r < 0)
+ fprintf(stderr, "error: Failed to add transform %s: %s\n", t,
aug_error_message(aug));
+
+ added_transform = true;
+ }
+
+ if (added_transform) {
+ r = aug_load(aug);
+ if (r < 0)
+ fprintf(stderr, "error: Failed to load with new transforms: %s\n",
aug_error_message(aug));
+ }
+
+ free(command);
+}
+
int main(int argc, char **argv) {
int r;
@@ -551,6 +588,7 @@ int main(int argc, char **argv) {
print_aug_error();
exit(EXIT_FAILURE);
}
+ add_transforms(transforms, transformslen);
if (print_version) {
print_version_info();
return EXIT_SUCCESS;
diff --git a/tests/run.tests b/tests/run.tests
index 55effdb..7567004 100644
--- a/tests/run.tests
+++ b/tests/run.tests
@@ -340,6 +340,29 @@ test get-bad-pathx -1 EPATHX
get /files[]
#
+# test transform
+#
+test transform-1 3
+ transform Test incl /tmp/bar
+ get /augeas/load/Test/lens
+ get /augeas/load/Test/incl
+prints
+ /augeas/load/Test/lens = Test.lns
+ /augeas/load/Test/incl = /tmp/bar
+
+test transform-2 4
+ transform Bar incl /tmp/foo/*
+ transform Bar incl /tmp/bar/*
+ transform Bar excl /tmp/foo/baz
+ print /augeas/load/Bar
+prints
+ /augeas/load/Bar
+ /augeas/load/Bar/lens = "Bar.lns"
+ /augeas/load/Bar/incl[1] = "/tmp/foo/*"
+ /augeas/load/Bar/incl[2] = "/tmp/bar/*"
+ /augeas/load/Bar/excl = "/tmp/foo/baz"
+
+#
# test print
#
test print-save 1
diff --git a/tests/test-api.c b/tests/test-api.c
index e74a6db..555582a 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -483,6 +483,52 @@ static void testToXml(CuTest *tc) {
aug_close(aug);
}
+static void testTransform(CuTest *tc) {
+ struct augeas *aug;
+ int r;
+ const char *v;
+
+ aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_MODL_AUTOLOAD);
+
+ r = aug_transform(aug, "Passwd", "/etc/passwd", 0);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_get(aug, "/augeas/load/Passwd/incl", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "/etc/passwd", v);
+
+ r = aug_get(aug, "/augeas/load/Passwd/lens", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "Passwd.lns", v);
+
+ r = aug_transform(aug, "Shellvars.lns_norec", "/etc/sysconfig/grub", 0);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_transform(aug, "Shellvars.lns_norec", "/etc/sysconfig/*", 0);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_transform(aug, "Shellvars.lns_norec", "/etc/sysconfig/network", 1);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/incl[1]", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "/etc/sysconfig/grub", v);
+
+ r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/incl[2]", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "/etc/sysconfig/*", v);
+
+ r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/excl", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "/etc/sysconfig/network", v);
+
+ r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/lens", &v);
+ CuAssertRetSuccess(tc, r);
+ CuAssertStrEquals(tc, "Shellvars.lns_norec", v);
+
+ aug_close(aug);
+}
+
static void testTextStore(CuTest *tc) {
static const char *const hosts = "192.168.0.1 rtr.example.com router\n";
/* Not acceptable for Hosts.lns - missing canonical and \n */
--
1.7.9.5
_______________________________________________
augeas-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/augeas-devel