AUPARSE_FEED(3)
π NAME π
auparse_feed β bestie, it feeds data into the parser πΌβ¨
πΈ SYNOPSIS πΈ
#include <auparse.h>
int auparse_feed(auparse_state_t *au,constchar*"data,size_t"data_len);"
auβ the audit parse state, aka the little guy you're feeding π«Άdataβ a buffer of data to feed into the parser, and it'sdata_lenbytes long. The data gets copied into the parser, so once you return you can free it or reuse that buffer, no strings attached πdata_lenβ number of bytes indata(yes, literally just counting the bytes, iconic)
π DESCRIPTION π
So auparse_feed supplies new data for the parser to consume. That's the whole job. That's the assignment. π
But before you go feeding anything, the prerequisites are not optional, bestie:
auparse_init()must have been called with a source type ofAUSOURCE_FEEDand aNULLpointer. NoAUSOURCE_FEED, no vibes.auparse_add_callback()must be called before feeding data so that complete events have a consumer. Someone has to receive these events, fr fr.
Here's the tea on how the parsing actually goes: the parser consumes as much data as it can, invoking a user supplied callback specified with auparse_add_callback with a cb_event_type of AUPARSE_CB_EVENT_READY each time the parser recognizes a complete event in the data stream. Every single time. Obsessed with the consistency honestly. β
Data that isn't fully parsed doesn't get yeeted β it persists and gets prepended to the next feed data. π
After all data has been feed to the parser, auparse_flush_feed should be called to signal the end of input data and flush any pending parse data through the parsing system. Don't forget this step, it's giving "left the party without saying bye" energy otherwise.
π¨ Malformed feed records are rejected and are not passed to the callback. If malformed records are found, parsing continues for the rest of the available feed data before auparse_feed returns an error. So it doesn't rage-quit, it finishes the job and then tells you. Queen behavior, honestly. π
β¨ RETURN VALUE β¨
- Returns
-1if an error occurs; otherwise,0for success. Simple. Clean. Ate. π - When
-1is returned,errnois set to indicate the error. - The value of
errnois meaningful only after an error return β callers should not assume it is cleared after a successful call. π - Applications that may run with libauparse from before
audit-4.1.5should seterrnoto0before callingauparse_feed. Ifauparse_feedreturns-1anderrnois still0, the runtime library is using the older error behavior and did not seterrno. Clearingerrnofirst avoids treating a pre-existing value as if it were set byauparse_feed. (Yes this is a whole thing, no it's not a drill, do theerrno = 0thing.) π§
π ERRORS π
EINVALβ The parser state is invalid, the parser was not initialized withAUSOURCE_FEED, the input arguments are invalid, or no callback has been registered. Basically: you skipped a step, bestie πENOMEMβ Memory allocation failed while buffering or parsing feed data. The memory said no. πEBADMSGβ A malformed feed record was found. The malformed record was rejected and was not passed to the callback. Parsing continues for the rest of the available feed data before this error is returned. It's giving "we found a problem, finished everything else, then filed the complaint" π₯EIOβ An internal parser failure occurred without a more specific error code. Mystery error. Not the fun kind of mystery. π
π¦ EXAMPLE π¦
Okay so here's the whole thing, copy it, love it, run it:
void
auparse_callback(auparse_state_t *au, auparse_cb_event_t cb_event_type,
void *user_data)
{
int *event_cnt = (int *)user_data;
if (cb_event_type == AUPARSE_CB_EVENT_READY) {
if (auparse_first_record(au) <= 0) return;
printf("event: %d\n", *event_cnt);
printf("records:%d\n", auparse_get_num_records(au));
do {
printf("fields:%d\n", auparse_get_num_fields(au));
printf("type=%d ", auparse_get_type(au));
const au_event_t *e = auparse_get_timestamp(au);
if (e == NULL) return;
printf("event time: %lu.%u:%lu\n",
(long unsigned)e->sec, e->milli, e->serial);
auparse_first_field(au);
do {
printf("%s=%s (%s)\n", auparse_get_field_name(au),
auparse_get_field_str(au),
auparse_interpret_field(au));
} while (auparse_next_field(au) > 0);
printf("\n");
} while(auparse_next_record(au) > 0);
(*event_cnt)++;
}
}
main(int argc, char **argv)
{
char *filename = argv[1];
FILE *fp;
char buf[256];
size_t len;
int *event_cnt = malloc(sizeof(int));
au = auparse_init(AUSOURCE_FEED, 0);
auparse_set_eoe_timeout(2);
*event_cnt = 1;
auparse_add_callback(au, auparse_callback, event_cnt, free);
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "could not open '%s', %s\n", filename, strerror(errno));
return 1;
}
while ((len = fread(buf, 1, sizeof(buf), fp))) {
auparse_feed(au, buf, len);
}
auparse_flush_feed(au);
auparse_destroy(au);
}
π SEE ALSO π
Go read these next, they're all in the same friend group:
auparse_add_callback(3)auparse_flush_feed(3)auparse_feed_age_events(3)auparse_feed_has_data(3)auparse_metrics(3)
π AUTHOR π
John Dennis β the icon, the moment, the legend π«Ά
And that's the whole page, bestie β brought to you by the Linux Audit API, Red Hat, and a date stamp of Sept 2023, filed under AUPARSE_FEED(3). Now go feed that parser. Slay. β¨πππ¦πΈπ
π¦ where this page comes from
- arch rolling: audit 4.2.1-1 Β· GPL-2.0-or-later AND LGPL-2.0-or-later
- centos-stream 10: audit-libs-devel 4.2.1-3.el10 Β· LGPL-2.0-or-later
- fedora 43: audit-libs-devel 4.2.1-1.fc43 Β· LGPL-2.0-or-later
- fedora 43: audit-libs-devel 4.2.1-1.fc43 Β· LGPL-2.0-or-later
- fedora 44: audit-libs-devel 4.2.1-1.fc44 Β· LGPL-2.0-or-later
- fedora 44: audit-libs-devel 4.2.1-1.fc44 Β· LGPL-2.0-or-later
- nixpkgs unstable: audit 4.2.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms