libcushions aims at adding support for url-like schemes to the glibc's fopen function. By using linker flags or the LD_PRELOAD environment variable, this can be done without modifying or even without recompiling the program, adding transparent support for archives files, or web urls, for example.
It comes with a full doxygen API documentation, for libcushions users or scheme handler implementors.
The latest version, can be download here.
IMPORTANT NOTICE: libcushions, while already potentially useful in some use cases, should be considered as a proof of concept.
The first part is libcushions itself, it proposes a minimalistic public
API with the cushions.h header. The cushions_fopen can be used directly in
a program, or one can use the -Wl,--wrap=fopen
flag at compilation to
transparently replace fopen calls on the fly with __wrap_fopen, which in
turn, will call cushions_fopen.
The third possibility is to set the LD_PRELOAD environment variable to the
path to libcushions.so, calls to fopen in the program executed, will be
replaced by calls to cushions_fopen transparently and with no compilation step
required.
The second central part is the url scheme handlers. They use the cushions_handler.h API to implement support for url schemes, by registering an handler with cushions_handler_register(). Some handlers are provided and are listed in the scheme support table at the end of this README.
These two following lines will simplify the next commands:
$ export LD_LIBRARY_PATH=.
$ export CUSHIONS_HANDLERS_PATH=handlers_dir
Build the relevant bits and create an example file:
$ make all examples
...
cc example/cp.c libcushions.so -Wl,--wrap=fopen -o example/cpw
cc example/cp.c -o example/cp
$ dd if=/dev/urandom of=tutu bs=1024 count=1024
1024+0 records in
1024+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0106583 s, 98.4 MB/s
example/cpw is built with the --wrap linker option, the fopen glibc symbol will be overriden by that of libcushions, the program will use it directly.
$ ./cpw file://tutu file://toto
$ md5sum tutu toto
91451e93db0faa7997536d7aa606cfe3 tutu
91451e93db0faa7997536d7aa606cfe3 toto
On the contrary, example/cp has been compiled without even knowing about libcushions, but using LD_PRELOAD, it's functionality can be added transparently:
$ ./cp file://tutu file://toto
./cp: fopen src: No such file or directory
$ rm toto
$ LD_PRELOAD=./libcushions.so ./cp file://tutu file://toto
$ md5sum tutu toto
91451e93db0faa7997536d7aa606cfe3 tutu
91451e93db0faa7997536d7aa606cfe3 toto
Now a more interesting example, our cpw program will download a file from an http web site and compress it on the fly in the lzop format:
$ python -m SimpleHTTPServer &
Serving HTTP on 0.0.0.0 port 8000 ...
$ ./cpw http://localhost:8000/src/cushions.c lzo://plop.lzo
$ lzop -df plop.lzo
$ md5sum plop src/cushions.c
de9cc9b40dd030524aacf08d910cf4f0 plop
de9cc9b40dd030524aacf08d910cf4f0 src/cushions.c
$ rm -f plop plop.lzo
$ fg # bring back HTTP server to foreground and kill it
<Ctrl + C>
Some other programs will be able to use libcushions unmodified, for example, if you want to:
-
compute the md5sum of the www.perdu.com webpage
$ LD_PRELOAD=libcushions.so md5sum http://www.perdu.com/
-
execute a lua script from a webpage:
$ LD_PRELOAD=libcushions.so lua http://download.redis.io/redis-stable/deps/lua/test/hello.lua