Skip to content

Commit

Permalink
Make it possible for aug_init to report initialization errors
Browse files Browse the repository at this point in the history
Sometimes initialization fails for mundane reasons, like syntax errors in
lens files. So far, it was not possible for callers to report details for
these errors, because they always got a NULL augeas handle back.

The new flag AUG_NO_ERR_CLOSE causes aug_init to return a handle even if
initialization fails, so that callers can use the aug_error* functions to
extract error details before calling aug_close.

  * src/augeas.c (aug_init): return a partially initialized struct augeas
    if AUG_NO_ERR_CLOSE is set
  * src/augeas.h (aug_flags): add AUG_NO_ERR_CLOSE
  * src/augtool.c: call aug_init with AUG_NO_ERR_CLOSE and print errors on
    initialization failure
  • Loading branch information
David Lutterkort committed Dec 2, 2011
1 parent 2d378d5 commit 93b695c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 19 deletions.
12 changes: 10 additions & 2 deletions src/augeas.c
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ struct augeas *aug_init(const char *root, const char *loadpath,
struct augeas *result;
struct tree *tree_root = make_tree(NULL, NULL, NULL, NULL);
int r;
bool close_on_error = true;

if (tree_root == NULL)
return NULL;
Expand Down Expand Up @@ -442,6 +443,10 @@ struct augeas *aug_init(const char *root, const char *loadpath,

result->origin->children->label = strdup(s_augeas);

/* We are now initialized enough that we can dare return RESULT even
* when we encounter errors if the caller so wishes */
close_on_error = !(flags & AUG_NO_ERR_CLOSE);

result->modpathz = NULL;
result->nmodpath = 0;
if (loadpath != NULL) {
Expand Down Expand Up @@ -538,8 +543,11 @@ struct augeas *aug_init(const char *root, const char *loadpath,

error:
api_exit(result);
aug_close(result);
return NULL;
if (close_on_error) {
aug_close(result);
result = NULL;
}
return result;
}

void tree_unlink_children(struct augeas *aug, struct tree *tree) {
Expand Down
17 changes: 14 additions & 3 deletions src/augeas.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ enum aug_flags {
what would have changed */
AUG_NO_LOAD = (1 << 5), /* Do not load the tree from AUG_INIT */
AUG_NO_MODL_AUTOLOAD = (1 << 6),
AUG_ENABLE_SPAN = (1 << 7) /* Track the span in the input of nodes */
AUG_ENABLE_SPAN = (1 << 7), /* Track the span in the input of nodes */
AUG_NO_ERR_CLOSE = (1 << 8) /* Do not close automatically when
encountering error during aug_init */
};

/* Function: aug_init
Expand All @@ -63,11 +65,20 @@ enum aug_flags {
* searched in. This is in addition to the standard load path and the
* directories in AUGEAS_LENS_LIB
*
* FLAGS is a bitmask made up of values from AUG_FLAGS.
* FLAGS is a bitmask made up of values from AUG_FLAGS. The flag
* AUG_NO_ERR_CLOSE can be used to get more information on why
* initialization failed. If it is set in FLAGS, the caller must check that
* aug_error returns AUG_NOERROR before using the returned augeas handle
* for any other operation. If the handle reports any error, the caller
* should only call the aug_error functions an aug_close on this handle.
*
* Returns:
* a handle to the Augeas tree upon success. If initialization fails,
* returns NULL.
* returns NULL if AUG_NO_ERR_CLOSE is not set in FLAGS. If
* AUG_NO_ERR_CLOSE is set, might return an Augeas handle even on
* failure. In that case, caller must check for errors using augeas_error,
* and, if an error is reported, only use the handle with the aug_error
* functions and aug_close.
*/
augeas *aug_init(const char *root, const char *loadpath, unsigned int flags);

Expand Down
34 changes: 20 additions & 14 deletions src/augtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,21 @@ static int run_command(const char *line) {
return result;
}

static void print_aug_error(void) {
if (aug_error(aug) == AUG_ENOMEM) {
fprintf(stderr, "Out of memory.\n");
return;
}
if (aug_error(aug) != AUG_NOERROR) {
fprintf(stderr, "error: %s\n", aug_error_message(aug));
if (aug_error_minor_message(aug) != NULL)
fprintf(stderr, "error: %s\n",
aug_error_minor_message(aug));
if (aug_error_details(aug) != NULL)
fputs(aug_error_details(aug), stderr);
}
}

static int main_loop(void) {
char *line = NULL;
int ret = 0;
Expand Down Expand Up @@ -478,18 +493,7 @@ static int main_loop(void) {
return ret;
if (code < 0) {
ret = -1;
if (aug_error(aug) == AUG_ENOMEM) {
fprintf(stderr, "Out of memory.\n");
return -1;
}
if (aug_error(aug) != AUG_NOERROR) {
fprintf(stderr, "error: %s\n", aug_error_message(aug));
if (aug_error_minor_message(aug) != NULL)
fprintf(stderr, "error: %s\n",
aug_error_minor_message(aug));
if (aug_error_details(aug) != NULL)
fprintf(stderr, "error: %s\n", aug_error_details(aug));
}
print_aug_error();
}
}
}
Expand Down Expand Up @@ -521,9 +525,11 @@ int main(int argc, char **argv) {

parse_opts(argc, argv);

aug = aug_init(root, loadpath, flags);
if (aug == NULL) {
aug = aug_init(root, loadpath, flags|AUG_NO_ERR_CLOSE);
if (aug == NULL || aug_error(aug) != AUG_NOERROR) {
fprintf(stderr, "Failed to initialize Augeas\n");
if (aug != NULL)
print_aug_error();
exit(EXIT_FAILURE);
}
if (print_version) {
Expand Down

0 comments on commit 93b695c

Please sign in to comment.