libdrgn: add string_builder_append_error()

This commit is contained in:
Omar Sandoval 2019-05-14 10:24:12 -07:00
parent e21ed988fb
commit efaec41ca2
3 changed files with 48 additions and 7 deletions

View File

@ -172,8 +172,9 @@ struct drgn_error *drgn_error_create_os(int errnum, const char *path,
*
* @param[in] file File to write to (usually @c stderr).
* @param[in] err Error to write.
* @return Non-negative on success, @c EOF on failure.
*/
void drgn_error_fwrite(FILE *file, struct drgn_error *err);
int drgn_error_fwrite(FILE *file, struct drgn_error *err);
/**
* Free a @ref drgn_error.

View File

@ -115,18 +115,49 @@ struct drgn_error *drgn_error_from_string_builder(enum drgn_error_code code,
return drgn_error_create_nodup(code, message);
}
LIBDRGN_PUBLIC void drgn_error_fwrite(FILE *file, struct drgn_error *err)
bool string_builder_append_error(struct string_builder *sb,
struct drgn_error *err)
{
bool ret;
if (err->code == DRGN_ERROR_OS) {
/* This is easier than dealing with strerror_r(). */
errno = err->errnum;
if (err->path)
fprintf(file, "%s: %s: %m\n", err->message, err->path);
else
fprintf(file, "%s: %m\n", err->message);
if (err->path) {
ret = string_builder_appendf(sb, "%s: %s: %m",
err->message, err->path);
} else {
ret = string_builder_appendf(sb, "%s: %m",
err->message);
}
} else {
fprintf(file, "%s\n", err->message);
ret = string_builder_append(sb, err->message);
}
return ret;
}
LIBDRGN_PUBLIC int drgn_error_fwrite(FILE *file, struct drgn_error *err)
{
struct string_builder sb = {};
char *message;
int ret;
if (err->code == DRGN_ERROR_OS) {
if (!string_builder_append_error(&sb, err) ||
!string_builder_finalize(&sb, &message)) {
free(sb.str);
errno = ENOMEM;
return EOF;
}
ret = fputs(message, file);
free(message);
if (ret == EOF)
return EOF;
} else {
if (fputs(err->message, file) == EOF)
return EOF;
}
return fputc('\n', file);
}
LIBDRGN_PUBLIC void drgn_error_destroy(struct drgn_error *err)

View File

@ -50,6 +50,15 @@ struct string_builder;
struct drgn_error *drgn_error_from_string_builder(enum drgn_error_code code,
struct string_builder *sb);
/**
* Append a formatted @ref drgn_error to a @ref string_builder.
*
* @return @c true on success, @c false on error (if we couldn't allocate
* memory).
*/
bool string_builder_append_error(struct string_builder *sb,
struct drgn_error *err);
/** Create a @ref drgn_error from the libelf error indicator. */
struct drgn_error *drgn_error_libelf(void)
__attribute__((returns_nonnull));