Right you are!
It doesn't use any sound/video/multimedia
Right you are!
It doesn't use any graphics, or mouse
Three for three!
Obviously, THEN... it is portable. But it would be portable to
Mac/windows/whatever too without much pain.
And here you've got a Nilges-grade error.
Lemme tell you what this hunk of code is. This'll drift a bit off topic,
but it's a very good example of how very non-portable a piece of code can
be. I would guess that I could get it running on OS X in a month or so,
but I am pretty sure it is semantically incoherent to talk about "porting"
it to Windows.
Background:
* Nearly all executables on Linux systems are dynamically linked, meaning
that they pick up the C library at runtime.
* Unix-like systems distinguish between "library" calls (made to code in
the C library) and "system" calls (made to the kernel).
* But actually, nearly all syscalls exist as tiny little stubs that are
found in the library and which contain the raw inline code to make a
syscall.
* The dynamic linker on Linux checks certain environment variables when
starting up, BEFORE it loads anything (including even the C library).
* These can cause it to do things like check paths other than the usual
system-wide linker path, and/or to load libraries BEFORE the shared
libraries a program was linked with, and which it was not linked with and
it has no knowledge of.
* The product I work on involves creating filesystems for embedded Linux
systems.
* Creating filesystems nearly always involves operations that require
root (sysadmin) privileges.
* It is extremely desireable that users not need root access on their
workstations to do it, though.
So.
The "hunk of code" alluded to above is a two-part thing. One part is a shared
library. Another part is a server. The shared library is designed such that,
if you put its name in the LD_PRELOAD environment variable, and a path to it
in the LD_LIBRARY_PATH environment variable, it will get picked up by any
dynamically-linked executable, and lookups of calls in it will pick up the
versions in this library BEFORE they pick up versions in the C library.
And it provides functions with the same names as a few dozen system calls,
and a couple of C-level library calls.
When you first hit one of these functions, it builds itself a table of the
"next" versions of all these calls (usually the ones in the C library, but
there could be other similar libraries; we don't care). And then it sets
up wrappers so that when you call the syscall open(), what you actually get
is my implementation of open(), which does some interesting magic stuff.
What this ends up doing is allowing me to intercept every system call that
deals with the filesystem and is affected by privileges, and act as though
you had root privileges, or at least, make it look as though it acted as
though you had root privileges. The client code does this by finding out
whether it has a server, and if not, starting a server, to which it then
sends messages informing the server about operations, or querying the server
about filesystem objects; the server maintains a database of files and
what to claim they are. So if you try to create a "device node" (a special
kind of Unix "file" which instead of having contents provides access to
the userspace interface of a device driver; e.g., a file named "sda1" might
end up hooked up to the first partition of the first SCSI disk on the
machine), what actually happens is:
1. I verify that there's not a file there, and if there is, fail
the same way the real syscall would have.
2. I create a plain file with no contents of that name.
3. If that succeeded, I send a note to the server telling it that
the file I just created should LOOK like it's a device node
with the given attributes.
Later, if you try to look at that file with, say, "ls -l", what actually
happens is:
1. I check the real file on disk.
2. I query the server about that path and file dev/inode (magic ID
uniquely identifying a file).
3. If I got anything back from the server, I replace the file's
"real" attributes with the attributes the server gave me.
4. I report back as though nothing happened.
There's a lot more, and some of it gets extremely arcane; there's magic
to intercept dozens of calls and do very surprising stuff.
The net result is that you can run an entire system install process and
end up with something which, viewed through this tool, looks just like a
properly-installed filesystem, complete with files owned by many different
users, device nodes, and everything. And then you can use other tools
which do things like create raw filesystem images or archives, and run
them in this magic mode, and get raw filesystem images which, dumped to disk
or flash, actually are working filesystem images with all the right modes.
The concept of porting this to Windows is frankly laughable. I could probably
get it working on BSD or OS X in about a month, give or take, but I'm not
totally sure; there's some pretty crazy assumptions in there, although I've
developed some neat trickery to allow this code to work even if some of the
"extra" calls it has don't exist on a given target. (e.g., some systems have
a family of calls with names like "openat()" or "unlinkat()" which allow you
to operate relative to a directory without having to specify the path to
that directory, others don't; my program wraps them if they exist, but works
fine even if they don't.)
Porting this between BSD and SysV in 1989 would have been much harder than
simply rewriting nearly all of it from scratch completely differently for
each, if it had even been possible to do it at all. (By 1990, you could
at least get ELF and dynamic linking on SVR4, so it might have been
possible there.) So, no, the Linux environment is NOT more fragmented than
the historical Unix market. They have greater code portability than anything
we ever saw back then.
-s