[augeas-devel] [PATCH] Add aug_transform and the transform command. Add -t|--transform option to augtool
David Lutterkort
lutter at redhat.com
Tue Aug 7 18:41:08 UTC 2012
On Fri, 2012-08-03 at 00:05 +0200, Raphaël Pinson wrote:
> 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
>
> ---
> src/augeas.c | 48 ++++++++++++++++++++++++
> src/augeas.h | 12 ++++++
> src/augeas_sym.version | 1 +
> src/augrun.c | 33 ++++++++++++++++
> src/augtool.c | 98 ++++++++++++++++++++++++++++++++----------------
> tests/run.tests | 21 +++++++++++
> tests/test-api.c | 39 +++++++++++++++++++
> 7 files changed, 219 insertions(+), 33 deletions(-)
I very much like the idea of this; it might be bikeshedding, but I'd
feel the syntax '-t FILE:LENS' would be more intuitive.
Some more comments:
> diff --git a/src/augeas.c b/src/augeas.c
> index 22ebd14..998d27b 100644
> --- a/src/augeas.c
> +++ b/src/augeas.c
> @@ -1729,6 +1729,54 @@ 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 r = 0;
> + char *lenspath = malloc(strlen(lens)+14);
> + int lenspathlen = sprintf(lenspath, "/augeas/load/%s", lens);
We never use malloc/calloc directly in Augeas; instead, we use the
macros from memory.h like ALLOC_N and REALLOC_N since they are much
safer.
In this case though, you should use
r = xasprintf(&lenspath, "/augeas/load/%s", lens);
ERR_NOMEM(r < 0, aug);
> + char *inclpath = malloc(lenspathlen+16);
> + sprintf(inclpath, "%s/incl[last()+1]", lenspath);
> +
> + char *lenslenspath = malloc(lenspathlen+6);
> + sprintf(lenslenspath, "%s/lens", lenspath);
> +
> + char *lensname;
> + if (strchr(lens, '.')) {
> + lensname = malloc(strlen(lens)+1);
> + strcpy(lensname, lens);
> + } else {
> + lensname = malloc(strlen(lens)+5);
> + sprintf(lensname, "%s.lns", lens);
> + }
Similarly, all these malloc + sprintf combinations should be replaced
with xasprintf (which is a safe wrapper around asprintf)
> + api_entry(aug);
You need to call api_entry as the very first thing in a public API
function, before doing anything that could produce an error.
> + ARG_CHECK(STREQ("", lens), aug, "aug_transform: LENS must not be empty");
> + ARG_CHECK(STREQ("", file), aug, "aug_transform: FILE must not be empty");
Do these checks right after calling api_entry, before doing any
allocations.
> + 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);
Actually, you could replace a lot of this by using some of the internal
tree_* helper functions, like tree_child and tree_child_cr. For example:
struct tree *xfm = tree_path_cr(aug->origin, 3, s_augeas, s_load, lens);
struct tree *l = tree_child_cr(xfm, "lens");
tree_set(l, lens);
...
Of course, there's lots of checking that none of those functions return
NULL that is missing.
> diff --git a/src/augtool.c b/src/augtool.c
> index ce4a8a3..0e202e7 100644
> --- a/src/augtool.c
> +++ b/src/augtool.c
> +static void add_transform(const char *t) {
> + char delims[] = "=";
> + char *lens, *file;
> + char *transform = strdup(t);
> + int r;
> +
> + lens = strtok(transform, delims);
> + file = strtok(NULL, delims);
strtok is one of those functions that everybody loves to hate (have a
look at the BUGS section in the man page) While its use in augtool
should be fine, you could do the same with
lens = transform;
file = strchr(lens, '=');
*file++ = '\0';
or for the syntax I'd prefer
file = transform;
lens = strrchr(file, ':');
*lens++ = '\0';
again with lots of checks for NULL etc. missing.
> @@ -551,6 +577,12 @@ int main(int argc, char **argv) {
> print_aug_error();
> exit(EXIT_FAILURE);
> }
> + while ((t = argz_next(transforms, transformslen, t))) {
> + add_transform(t);
> + added_transform = true;
> + }
>
> + if (added_transform)
> + r = aug_load(aug);
Stylistically, I'd do all this in add_transform (and rename it to
add_transforms)
> diff --git a/tests/test-api.c b/tests/test-api.c
> index 5726540..ef9cce5 100644
> --- a/tests/test-api.c
> +++ b/tests/test-api.c
> @@ -455,6 +455,45 @@ static void testToXml(CuTest *tc) {
> aug_close(aug);
> }
>
> +static void testTransform(CuTest *tc) {
I am perfectly happy to do most of these tests in run.tests; the only
tests that need to go into test-api.c are ones where we need to test a
specific behavior of the API call, and can't do that from run.tests -
usually only tests that check specific error returns and the like,
though even most of those can be done from run.tests.
David
More information about the augeas-devel
mailing list