netatalk: Error checking and logging

netatalk 4.5.1
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
Error checking and logging

We want rigid error checking and concise log messages. At the same time, we want to avoid overly verbose code where the relevant function call is buried in error checking and logging statements. In order to address both error checking and code readability, we provide a set of error checking macros in <atalk/errchk.h>. Every macro comes in four flavours: EC_*CHECK*, EC_*CHECK*_LOG, EC_*CHECK*_LOGSTR and EC_*CHECK*_LOG_ERR where CHECK should be substituted with one of the supported tests:

- ZERO - the value equals 0
- NULL - the value equals NULL
- NEG1 - the value equals -1

To explain the loggging logic of each error checking macro flavor, using the ZERO test as an example:

- EC_ZERO checks that the value equals 0 with a standard log message
- EC_ZERO_LOG additionally logs the stringified function call
- EC_ZERO_LOGSTR allows specifying an arbitrary string to log
- EC_ZERO_LOG_ERR allows specifying the return value

The macros EC_CHECK* unconditionally jump to the cleanup label defined by the EC_CLEANUP macro where the necessary cleanup can be done alongside validating the return value.

# Examples

stat() without EC macro:

static int func(const char *name) {
int ret = 0;
...
if ((ret = stat(name, &some_struct_stat)) != 0) {
LOG(...);
/* often needed to explicitly set the error indicating return value */
ret = -1;
goto cleanup;
}
return ret;
cleanup:
...
return ret;
}
LOG
#define LOG(log_level, type,...)
Definition logger.h:148

stat() with EC macro:

static int func(const char *name) {
/* expands to int ret = 0; */
EC_INIT;
char *uppername = NULL;
EC_NULL(uppername = strdup(name));
EC_ZERO(strtoupper(uppername));
/* expands to complete if block from above */
EC_ZERO(stat(uppername, &some_struct_stat));
EC_STATUS(0);
EC_CLEANUP:
if (uppername) {
free(uppername);
}
EC_EXIT;
}
EC_CLEANUP
#define EC_CLEANUP
Definition errchk.h:28
EC_ZERO
#define EC_ZERO(a)
Definition errchk.h:88
EC_INIT
#define EC_INIT
Definition errchk.h:18
EC_EXIT
#define EC_EXIT
Definition errchk.h:29
EC_STATUS
#define EC_STATUS(a)
Definition errchk.h:19
EC_NULL
#define EC_NULL(a)
Definition errchk.h:168
NULL
#define NULL
Definition utf8util.c:47

A boilerplate function template is:

int func(void)
{
EC_INIT;
...your code here...
EC_STATUS(0);
EC_CLEANUP:
EC_EXIT;
}