intfs - filesystem for intensional files.

This filesystem allows file contents to be expressed in terms of
programs to generate the contents.  It allows simple user space
filesystems to be constructed without the effort of having
to write a full userfs filesystem.

To mount, use
	muserfs intfs <mount-point> <base-dir>

The <base-dir> is a directory tree which is to be mirrored.  The intfs
filesystem will appear as a tree of directories in the same shape as
the base directory, except containing symlinks to the original files
rather than images of them.  Symlinks in the base directory tree appear
unchanged in the mirrored tree (that is, the link contents point to the
same place).

Normally a symlink contains a pathname to another file or symlink,
relative to the directory containing the symlink.  In this case, if
the symlink points to a path starting with "#!", the rest of the path
is treated as a script for /bin/sh.  When the file is read, the
command is actually executed, and the stdout and stderr is read as the
file contents.  If you do a fstat on the open file descriptor, it
appears to be a pipe or fifo file.

For example (commands typed in a mounted intfs filesystem):
$ ls -l
lrwxrwxrwx   1 jeremy   users          16 May 13 19:58 file.gz -> /usr/tmp/file.gz
lrwxrwxrwx   1 jeremy   users          14 May 13 19:58 file -> #!zcat file.gz
$ cat file
This is a compressed file

So, as you see, file contents can be generated on demand.

HOW IT WORKS

This works by having different code for the up_readlink and
up_followlink operations.  Normally, reading the link gives you the
literal path of the file which is being referred to.  However, it is
possible to have a symlink which goes to a different place when
followed than would appear from reading it.

A userfs filesystem still has to return a pathname for a file as a
result of a up_followlink operation, so intfs has a special directory
".fifo" in the mount directory which contains transient FIFO files.
When a normal link is followed, intfs just returns the link contents
as read by readlink.  For intensional links (those starting with
'#!'), it returns a relative path to a fifo file in .fifo.  The fifo
file only exists in the directory for a very short time: it is removed
when that path is opened or when the inode is "iput", which ever comes
first.  Therefore, if the link is being followed for opening, it can
be opened once before the name disappears.  If the link is followed
for something else, like a stat, it will be "iput" immediately,
without ever being read.

There is a race-condition: if an intensional file is being stat'd,
then it does appear in .fifo, so something else could open it and
read it.

If intfs can (if its running as root), it tries to execute the command
with the permissions of the program reading the file.  It gets these
permissions from the credentials passed when the file is opened.
Because the filename is removed from .fifos as soon as it is opened,
nothing else can open the file and get the output of the program
executing for another user.  The program is run with the same
environment as intfs, with a current directory in the corresponding
place in the base filesystem.

This is an experimental filesystem, and so has some problems.  In
paritcular, it doesn't keep track of the underlying filesystem changes
very well, so its best to do all the file rename/deletion/ creation
through the intfs filesystem.

THe basic idea for intfs came from Paul Eggert and D. Stott Parker's
paper in the 1992 Usenix File Systems Workshop Proceedings, which
presented IFS0, a filesystem having properties similar to intfs, but
implemented in SunOS shared libraries.  They followed this work up
with the IFS1 filesystem, presented in the Usenix Winter 1993
Technical Conference proceedings.  The library approach is probably
more suited for this filesystem than using userfs, but I had userfs
and haven't found out how to make Linux shared libraries, so here it
is.

	Jeremy Fitzhardinge
	jeremy@sw.oz.au
