That thread indicates that the reason swift-system does not expose errno is not because it is out of scope for the package - rather, that the language does not provide the tools necessary to expose it safely. Any other Swift library would have the same difficulty properly exposing errno.
As the roadmap you linked to indicates, the scope of the package is also not limited to basic file reading and writing. And the goals of the package seem to include everything that was asked for.
There are many reasons for swift-system currently being so limited. I suspect some of it, again, has to do with language limitations.
I'll give a concrete example: @tera mentioned getifaddrs. If you're not familiar with that call, here's the linux man page. Basically it returns a linked-list of the following elements:
struct ifaddrs {
struct ifaddrs *ifa_next; /* Next item in list */
char *ifa_name; /* Name of interface */
unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */
struct sockaddr *ifa_addr; /* Address of interface */
struct sockaddr *ifa_netmask; /* Netmask of interface */
union {
struct sockaddr *ifu_broadaddr;
/* Broadcast address of interface */
struct sockaddr *ifu_dstaddr;
/* Point-to-point destination address */
} ifa_ifu;
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
void *ifa_data; /* Address-specific data */
};
Notice all of these pointers - not only to the next item in the list, but also strings and other values. When you call freeifaddrs it not only frees the linked list, it frees all of that data as well, making these dangling pointers.
Doing what @tera suggested and eagerly copying the linked-list in to array is therefore insufficient. We would also need to eagerly copy all of this other data (and copying the ifa_data member could be especially awkward). That's a lot of overhead for a low-level system library. Let's say I have a particular interface address and want to find the name of only that interface - the eager version would do a lot of unnecessary work.
Once you start eagerly copying everything, you introduce so many overheads that some people will inevitably get frustrated with it and drop down to using the unsafe C functions directly. It's not a strategy that scales well to all APIs and use-cases.
Alternatively, with better support for non-copyable types, we could pair the getifaddrs/freeifaddrs calls in a non-copyable iterator. The struct shown above could be a non-escaping type with a lifetime dependency on that iterator, with data exposed as more ergonomic types (e.g. exposing name as a String) via computed properties. I think this would be a much better approach - it adds safety and ergonomics to the C interface, without any overheads.
For instance, you'd be able to write something like this:
func getInterfaceName(_ addressToFind: Address) -> String? {
for info in getifaddrs() /* would probably have a better name */ {
if info.address == addressToFind {
return info.interfaceName
}
}
return nil
}
And it would be exactly as fast as if you'd used the unsafe C APIs directly.
(Just to be clear: I don't know if this is the design the swift-system maintainers would choose, but it's the kind of design I would want from it. It's safe, it's ergonomic, it's swifty, it's fast.)