Currently, getting and listing attributes is inconsistent in how it
deals with allocating memory for the data returned by the syscall:
- in most cases, we ask the kernel for the value, allocate memory,
then retrieve the value; if the value changed (increased) in the
meantime, this will lead to what should be preventable failures
- in the single case of getall, there is a loop for getting the
individual values, but not for initially get the list of values
Hence the bug report #12. This rather large change refactors a lot of
the code:
- doing a get/list is abstracted away into a helper function that
always does retries until we can read the value or fail with a
different error than ERANGE; this helper deal with all allocations
and resize operations.
- this means most of the single get/list operations are heavily
simplified
- and also means that we can always start optimistically with an
initial buffer size (currently set to 1K), instead of asking the
kernel first: this saves one out of two syscalls in the case the
value will indeed be smaller, but adds one extra syscall (the failed
initial read) in the case it's not.
The optimisation is a double-edged sword: for small attributes, it
will be a win (e.g. the test suite is ~5% faster now), but for large
attribute/lists, it will be potentially slower (50% more
syscalls). Not sure how to nicely deal with this; it would be good to
have a keyword argument maybe? Or build flag? Left for future
enhancements.