I have found a function called fmemopen on the
http://www.gnu.org/ site,
which seems to exactly what I need and seems to be in some elusive version
of stdio.h. Only problem is I dont seem to be able to find the source code.
fmemopen() is not standard, so there is no assurance that you
have one.
I added a generalized "function-oriented" stdio interface to 4.xBSD,
which is now in NetBSD and FreeBSD. Here, rather than a specific
"open memory region" function, there is an "open these functions"
function. You provide functions that implement reading, writing,
and/or seeking -- at least one of read and write is required --
and closing, along with a "void *" value. Your provided functions
will be called to accomplish data transfers. (For optimization
purposes you are allowed to call setvbuf() to attempt to redirect
future read/write operations to specific areas of memory, but you
must be prepared for this to fail or be overridden by the user.)
Given funopen(), you can implement the equivalent of fmemopen().
You can also implement a "FILE *" stream that sits atop a compression
algorithm, or a "FILE *" stream that implements encryption, or
any other trick you like. You can stack these on top of each
other because each one is just a "FILE *":
struct compression_data {
FILE *substream;
... more data here as needed ...
};
static int compress_write(void *cookie, const char *data, int len) {
struct compression_data *p = cookie;
... do whatever it takes to compress the data and write it
to p->substream ...
return number_of_bytes_transferred; /* or -1 for error */
}
FILE *compressed_output_stream(FILE *substream) {
FILE *rv;
struct compression_data *p;
if ((p = malloc(sizeof *p)) == NULL)
return NULL;
p->substream = substream;
rv = funopen(p, NULL, compress_write, NULL, compress_close);
if (rv == NULL)
free(p);
return rv;
}
struct encryption_data {
FILE *substream;
...
};
static int encrypt_write(void *cookie, const char *data, int len) {
struct encryption_data *p = cookie;
... do whatever it takes to encrypt the data and write it
to p->substream ...
return number_of_bytes_transferred;
}
FILE *encrypted_output_stream(FILE *substream, ...) {
FILE *rv;
struct encryption_data *p;
if ((p = malloc(sizeof *p)) == NULL)
return NULL;
p->substream = substream;
... handle additional details like keys here ...
rv = funopen(p, NULL, encrypt_write, NULL, encrypt_close);
if (rv == NULL)
free(p);
return rv;
}
Now you can get an encrypted compressed file like this:
FILE *bottom, *middle, *top;
out = fopen("foo.encrypted.compressed", "w");
middle = out ? compressed_output_stream(out) : NULL;
top = middle ? encrypted_output_stream(middle, ...) : NULL;
Now ordinary fprintf()s to "top" will encrypt, then compress, then
write. (Each "close" function, not shown here, has to push any
unwritten data through, of course.) Attempts to fseek() on "middle"
and "top" will be rejected since there is no underlying seek
function. (Supporting seeks within compressed or encrypted files
is generally difficult.)
Alas, funopen() is likewise nonstandard.