|[AD] Low-level Packfile Hooks|
[ Thread Index |
| More lists.liballeg.org/allegro-developers Archives
Some two and a half years ago I committed a deadly sin. I used DJGPP's File
System Extensions in Rock 'n' Spin, one of my games. These extensions allow
the user to intercept file access at a very low level, certainly below
Allegro's packfile structures, and I used them to apply a (probably not
very) strong encryption algorithm to a file after the compression phase.
Now, 99% of Allegro users have had NT-based Windows, dodgy hardware, or
both, forced on them, and my game is festering away in the mists of time
(how's that for a mix of metaphors? :) until such a time as I can port it to
Windows and Linux.
I propose, therefore, to write a low-level packfile hooking system. I won't
be the only person to find this useful; someone who goes by the name of
MikeDX on IRC EFnet #allegro wants to use functions like load_bitmap() and
load_sample() (which use PACKFILEs) to load files from images in memory. The
system I have in mind will require simple mechanical changes to src/file.c
and some extra code to be written.
The PACKFILE system (see src/file.c) is built on top of several functions
from unistd.h, including open(), close(), dup(), lseek(), read() and
write(). These functions operate on file descriptors (ints typically named
fd). The only platform that has special-case handling is the Mac, for which
src/mac/mfile.c provides a wrapper to open() and the other unistd.h
functions are used as normal. The wrapper seems only to translate the
filename into a Mac-formatted path.
My changes would have the existing PACKFILE system operating on virtual file
descriptors. Each virtual file descriptor would have a set of hook functions
associated with it, and these would be called instead of the above lseek(),
read(), etc. The parameters would be the same in each case (except that the
fd would be virtual). dup() wouldn't be hooked, but would be replaced with a
special version that works on virtual fd's; the underlying dup() wouldn't
actually be needed, but this is unimportant.
open() is a special case, since it has to generate an fd rather than take
one. The user would add a series of 'open hooks'. Any calls to open() would
be replaced with an algorithm that calls the open() hooks in turn, giving
each the opportunity to hook the new fd (the most recently registered hook
has first refusal). If no hook accepts the new fd, a default hook is
installed; this default hook chains to the underlying open() implementation.
When an open hook takes control of an fd, it can allocate memory and call a
function to store a void * pointer with the fd. Then the other functions can
request the void * pointer by calling another function. The close() hook is
then responsible for freeing it. However, it is not necessary to use the
void * pointer.
If an open hook needs to open a file of its own, it can call a special
Allegro function. This function will defer to _al_open() on the Mac or
open() on other systems.
Before I go ahead and code this, I have a few questions:
Will the changes be accepted? I'll test it myself, especially making sure
that the existing packfile functionality isn't crippled.
How portable are these unistd functions? DJGPP's libc docs list them as
POSIX, which means MSVC might be obfuscating the function names for no
reason - but at first sight I couldn't find any preprocessor magic in
Allegro's headers to get around such a problem. I don't have MSVC myself.
Can anyone confirm what the situation is?
Any other suggestions of ways to improve the system (without making me do a
lot more work :)?
MSN Photos is the easiest way to share and print your photos: