There is no reason to specify encoding here, it's file system that should do it, e.g. ZFS has an option to enforce UTF-8.
Correct, and that's a step forward. When all processes that use a file system have been moved to use UTF-8, then you can turn that option on, and it gives you some (albeit not perfect) protection against processes creating files or directories with names that are not valid UTF-8. But you have to remember that the Posix interface has very few restrictions on what file names can be: They have a maximum length (which is set per file system, not universally), and they can not contain the Nul character nor the slash character. All other binary bytes (form 0x01 to 0xFF excluding 0x2F = "/") are valid. Enforcing that all file names are valid UTF-8 immediately breaks Posix, and on an existing system, it may make certain files inaccessible.
But what's worse is that by design the file system has to be encoding agnostic: When you create a file or directory, an opaque string of bytes (not displayable characters) is passed into the file system. For example, the file system may see a file whose name is the two bytes 0xC0 0xB0. It does not know whether the file name is to be interpreted as the 8859-1 characters "A accent degree", or as a single UTF-8 character that I can't be bothered to look up, or whether the user intended the two bytes to be binary (non-displayable data). The reason for this is that the file system code (in the kernel) can not know what encoding the process (in user space) is using. Now imagine that this is a computer that is using a mix of user processes, some using 8859-1 and some UTF-8: Someone creates a file that has one name, and someone else sees a file with a different name. Once you start using non-normalized sequences, you can even have cases where two files have the same name in certain locales, which violates the invariant that no two files in the same directory have the same name. If you've ever tried this (and I have, since I used to implement file systems): it causes lots of utilities (like ls or tar) to behave very badly.
Windows uses UTF-16 (previously used UCS-2), so it's not valid example; and there's experimental support for UTF-8, so it's moving in this direction.
Cool, perhaps Windows can become completely UTF-8 eventually. That would be nice.
Could you please elaborate?
There are many reasons why I don't like C/C++ and Posix, and lack of support for distinguishing between "array of bytes, which are to be interpreted as binary" and "string of characters, which are encoded in a certain locale" is one of them. And that is exactly the case described above: The open system call has as an argument as "char * path". We have no idea whether those are binary bytes (which would be valid), or a character string which may have to be transcoded and which should have its normalization checked. Certainly, the C/C++ language would be capable of creating a new data type for "displayable string that is subject to encoding and locale rules", but to make that universally used, we'd have to change both the language standard, and the Posix standard that uses the old-style language bindings.
There are many other things I don't like. A few examples include hard links, sparse files, temporary files (link-count zero files), the ability to modify files in place, the dichotomy between read/write and mmap access, the various 2^64 limits, and so on.