--[ Lowest Common Denominator
Lowest Common Denominator has two definitions as a noun, one mathematical and
one figurative. Merriam Webster Dictionary mentions that the first usage in
the mathematical context came about around 1851 while other sources mention
that the figurative use started much around approximately the same time
as shown in the passage below which was found in Wheeling [West Virginia]
Daily Intelligencer published on October 18, 1873.
--- original source: https://english.stackexchange.com/a/514591
The feeling between the Cincinnati Commercial and Gazette, is probably
reduced to its lowest common denominator in the following paragraph in an
editorial in yesterday's Commercial:
"The effusion of malice and stupidity in the Gazette about the Commercial
is of no personal consequence or public interest. It is the green ooze of
an ancient jealousy, and, though offensive, is innocuous."
---
This is a long winded way of saying that we have been looking down on things
that have been produced to have the widest appeal possible. Now let's get
technical.
--[ POSIX
POSIX or Portable Operating System Interface refers to a family of standards
which were first defined around 1988. Notice the first word 'Portable'.
Does POSIX matter in today's world where there is almost a monopoly when it
comes to open source OS's, i.e Linux?
Well, you know which other widely used (more widely in consumer devices than
Linux, that is) is POSIX compliant? Mac OSX. And since Windows users now have
access to Linux via WSL2, we can target POSIX and cover all three popular OS's.
So what's the problem? Well, let's look at a specific case, namely, listing
files within a directory.
--[ Reading Directories
For files, you have nice POSIX defined interfaces which directly map to
Linux system calls:
* open
* read
* write
* close
You would expect to have analogous interfaces for directory access, which
maps directly to system calls with minimal overhead. The issue is that POSIX
only provides the only high-level interfaces:
* opendir
* readdir
* closedir
What's the issue with these interfaces? Well unlike read() and write() which
allows you to slurp as much data as you have buffer size for, readdir()
will only return data for one directory entry per call (which is a dirent
structure).
Now surely there should be some way to read more than one directory entry
per function call, right? Well let's look at the system call that Linux
provides for the purpose:
* getdents/getdents64
This allows us to use normal open and close for accessing the directory fd
while also allowing us to read more than one directory entry at a time. It
also has the nice property of mapping directly to the underlying syscall.
The problem? It's not in the POSIX interface, so you can't use it anywhere
else. Well you can kind of use getdirentries64 syscall on Mac OSX, but as
discovered by the Golang team, Apple is not going to allow you to use it.
--- original source: https://go-review.googlesource.com/c/go/+/168479
syscall: avoid _getdirentries64 on darwin
Getdirentries is implemented with the __getdirentries64 function
in libSystem.dylib. That function works, but it's on Apple's
can't-be-used-in-an-app-store-application list.
Implement Getdirentries using the underlying fdopendir/readdir_r/closedir.
The simulation isn't faithful, and could be slow, but it should handle
common cases.
Don't use Getdirentries in the stdlib, use fdopendir/readdir_r/closedir
instead (via (*os.File).readdirnames).
---
And oh, its not even described in the man page and its predecessor,
getdirentries,is now deprecated and in its man page they recommend the
POSIX interface.
--- original source: https://keith.github.io/xcode-man-pages/
getdirentries.2.html
getdirentries() should rarely be used directly; instead, opendir(3) and
readdir(3) should be used.
As of Mac OS X 10.6, getdirentries() is deprecated, and it is recommended
that applications use readdir(3) rather than using getdirentries() directly.
Due to limitations with the system call, getdirentries() will not work with
64-bit inodes; in order to use getdirentries(), _DARWIN_NO_64_BIT_INODE must
be defined. See stat(2) for more information on _DARWIN_NO_64_BIT_INODE and
its other effects.
---
--[ Simplicity vs LCD vs Complexity
So what are the choices that we have?
* Use readdir and forget about reading multiple directory entries at a time
* Use IFDEFs to use getdirent on Linux and readdir everywhere else
* Focus only on Linux and use getdirent and forget about portability
When you want something to work across multiple OS's and hardware, you
can either embrace complexity by having specific code for each one, which
in-turn increases your own burden and the maintainability of the code or you
can fall back on the Lowest Common Denominator which means that even if some
subset of platforms offer additional features, you can't make use of the same.
Or you can forget about all of this and focus on a specific platform and save
your sanity. Linux is kind of ubiquitous so focus on that but if you shipping
something like a Game, you can't rely on WSL to save you on consumer devices.
Anyways, I wrote this down to document the rabbit hole I went down just to
read some directory entries.
--[ Index ]--