are filesystems on linux just safer than the network subsystems or do filesystems just never expose any interface besides posix i/o so they have a much smaller and better-characterized attack surface?
Post
i did think it was cute to make readdir() call getdents() (although i think readdir() should be deprecated because "mysterious pointer not valid across invocations" is just a bad omen)
"maximum size of dirent record across entries of this directory" could be a neat API. or a maximum entry size for the whole filesystem. just something that gives you a guaranteed minimum buffer size that will always store at least one record
it's very fucked up that the filesystem conflates:
- write data into OS buffer
- make data visible to all other processes
- make data persist to disk
each are individually problematic because they fail to represent application-specific constraints. but on top of their individual failings they also can't be distinguished from each other. that's two levels of conflation
you might say "ohohoho but of course there is le fsync mon cheri" and yes that's correct there is a single method conflating global visibility and persistence! but write() is generally eventually consistent and may even get persisted without fsync()! the filesystem offers no way to hint that write() output doesn't need to be visible or persisted until synced!
so the filesystem tries to infer scheduling criteria from the sequence of read/write/seek calls on the current fd, which is very much like fortune telling in that it infers generic and unhelpful things about your future
i'm also coming back as usual to @zwol's proposed transactional operations. i think "transactions" makes people think of it like a database, where a transaction tries to perform multiple global state changes in sequence atomically. i think "scratch space" is a much more common requirement. i want "make an anonymous dirfd, let me populate it, then hook it up to the rest of the world at this path". hell, let me reserve a file/directory entry at a given path so open()/opendir() calls fail until i release the token or commit the result
imagine if at any point in between lines of code in $LANG someone could modify the values of any variables in the current scope. and add some new variables to the stack
also it's unclear to me why io_uring needs to share buffers between kernel and userspace when getdents() just provides the buffer to the kernel to copy into. either io_uring is wrong or getdents() is wrong