Zero often means success because zero is the only integer value that evaluates to false. All other integer values evaluate to true and they are meant for various error codes.
It might seem a bit weird and logically inverted, but because success is just success and errors can be different, the above convention is chosen often.
In fact, this is the most rational convention if the return value of a function is used not only as a success/failure indicator, but as an error code too. If the error code is stored, say in an additional output parameter, then returning 1
for success and 0
for failure makes more sense.
Imagine what the condition would be in the case of 0
being success:
if (errcode = func()) {
/* error handling */
}
versus the more cumbersome:
if ((errcode = func()) != 1) {
/* error handling */
}