As an example, look at a tiny portion of the Access Control List (ACL) API on Linux. The
API is symmetric in that there is an acl_get_file(3) counterpart for the acl_set_file(3)
system call, but it is in the error cases where the introspection fails.
int acl_set_file(const char *pathname, acl_type_t type, acl_t acl);
this system call can fail with numerous errno values, we will look at just two of them
- because the acl argument is too big for the file-system referred to by pathname.
- because type is not one of 2 specific values (or 3 on FreeBSD)
- you tried to set a directories-only acl on a non-directory (you tried to set an NFS attribute on a non-NFS file system)
- something else
For case (2) it is possible to work out the problem.
For case (3) it is also possible to work out.
But for case (1) how big is too big? Where is the pathconf(2) query to
tell you this maximum? Note FreeBSD has this (_PC_ACL_PATH_MAX), but not Linux. This information is necessary so that you can help the user out and tell them a
little about how to fix the problem.
And while we look at the “too big” case, there is no function to determine how many entries are present, the misleadingly named acl_size(3) has minimal usefulness on Linux, because it reports the size in bytes of the on-disk representation. However on Linux ext2/3/4 file systems all extended attributes for a file must fit into a single disk block. So, the presence of other extended attributes will change the available storage.
1. the filesystem does not support ACLs.
2. the host system does not support ALSs.
3. The host system supports ACLs but they are disabled.
For case (1) where is the pathconf(3) call to determine whether or not he
filesystem supports ACLs? Note : FreeBSD has pathconf(_PC_ACL_EXTENDED), but not Linux. Is there an ACL mount option to muddy the waters? Yup user_xattr on Linux and acls, on FreeBSD, oh joy.
For case (2) where is the sysconf(3) call to determine whether or not the host system supports ACLs? And this may be the same thing as case (3) or not.
Often the strerror(3) system call is all the introspection you get for errors, and it’s hideously limited and cryptic. Which is why libexplain exists. Libexplain is why I care about APIs including introspection, you can’t produce good error messages without it.
Set Get Symmetry
Another facet of introspection is simpler: if you can set it, you should be able to get it, with a minimum of fuss. I recall one system I worked on with a heap of set functions, but if you wanted to *get* any of those values, you had to use SQL. That isn’t a symmetric API.
Another classic example, is the abiliy to have “holes” in Unix files. But absolutly no way to find them. It was decades before the SEEK_DATA and SEEK_HOLE whence values were added to lseek(2). The ability to make holes, but the inabiliy to find them is not a symmetric API.