.HTML "Shifs - a simple way to transform and build dynamic file servers .ds CH .FP lucidasans .de SS .NH 2 .. .TL Shifs A language to build dynamic file servers .AU Uriel M. uriel @ cat-v.org .AB .PP .I Shifs allows you to easily transform and generate simple dynamic file systems that can be implemented directly from the command line and can take advantage of the standard tools used to manipulate text streams. .I Shifs is still only a prototype but it is already functional enough to be useful not only for experimentation but also in production environments. .AE \" .2C .NH Introduction .PP .I Shifs uses a very simple language to define a set of .I patterns that trigger .I actions . In that sense it is similar to .I awk but instead of handling text streams, it works with file trees. .I Shifs was born out of the desire to have a simple way to transform and extend the data exposed by file server in a generic and extensible way. Editing the source of existing file servers is too intrusive and makes it harder to maintain backward compatibility for applications that might expect the old interface. One could avoid that in some cases by adding new synthetic files to the file server that would export the data in the desired format, but that clutters the file server with files that might have a very specialized purpose that is not related to the function of the file server itself and would violate the core principle of doing one thing and doing it well. In other cases access to the file server might not be available, or one might want to transform a whole tree that might include files exported by different servers. .PP Another goal was to make it convenient to leverage the power of the standard application toolset of the operating system and in that way bring the .I software-tools philosophy to the world of dynamic file server creation, and do so in a secure and convenient way. .PP The more immediate task that prompted this interest was the need to overhaul the HTML generation code in .I wikifs which consists of almost a thousand lines of C code used to first parse the internal text format of wiki pages and then generate the HTML output. Considering that the same task could be accomplished by a dozen lines of awk and other standard tools, it appeared worthwhile to take advantage of that approach without discarding the convenience of a file system interface. .NH Suckfs .PP A first attempt was made to implement in C a complete language called .I suckfs (because it . I sucks files) in the spirit of awk where rules would match path names and actions would dynamically generate or transform the contents of the matched files. But soon it became clear that the language would need to be too complex to perform even the most simple tasks, and it failed to accomplish the main goal that was to take advantage of existing tools and languages without adding extra complexity. Also it was appreciated that it would be convenient if the facility could be available on as many platforms as possible. Inferno provided this and was a good opportunity to experiment with Limbo. In hindsight this was a very good choice as it simplified some problems considerably. In particular using the .I sh module made everything much easier. .NH The shifs language .PP The language was simplified to the bare basics, providing a foundation that could be extended in the future as more complex interactions become feasible while delegating all the procedural heavy lifting to the Inferno .I sh module. The language has a syntax somewhat similar to .I awk and .I mk ; consisting of .I rules , each composed of a .I pattern and a set of .I actions . .NH 2 Patterns .PP A pattern starts at the beginning of line and consists of an operation specifier ( .I r for read, .I w for write, etc. ), in the absence of any operation specifier .I r is used; followed by the regexp match operator .I ~ (other operators might be added in the future), the rest of the pattern up to the end of line or a trailing .I ~ is the argument to the regexp operator which is a regular expression that will be matched against file paths. .PP \" .1C .KF .P1 r ~[0-9]+/[a-z]+$ .P2 .ce .I "Figure 1. Sample shifs pattern" .KE .PP .NH 2 Actions .PP To complete a rule, a set of .I action lines follow the pattern line, action lines should begin with a .I tab character and use the Inferno sh syntax. \" .1C .KF .P1 r ~^today$ date | sed 's/ .*//' .P2 .ce .I "Figure 2. A complete shifs rule" .KE .PP If the action is short it can also follow the second .I ~ in the pattern, for example the previous example could be rewritten as: \" .1C .KF .P1 r ~^today$~ { date | sed 's/ .*//' } .P2 .ce .I "Figure 3. A complete shifs rule in a single line" .KE .PP The braces around the action are handled by the sh module and are included for clarity. .PP The environment in which actions are run includes some convenient variables set by shifs before the action is run, of special interest is .I $FPATH which contains the full path that matched this rule. .NH Execution .PP It is easy to run .I shifs from a terminal window. .B shifs [ .B -po ] [ .B -r .I /source/tree ] [ .B -m .I /mount/point ] [ -f .I rulesfile | .I rules ] .PP The .I -p option allows to 'pass-thru' files that don't match any rule so they are retrieved unchanged from the underlying file server. The .I -o makes the exported file system read only. The path passed to .I -r is used as starting point for the exported file tree, and actions use it as their working directory, if the .I -p options was used all the files under that tree that don't match any rule will also be accessible without any modifications, if .I -r is not used the current working directory is used instead. Rules can be specified directly from the command line or can be read from .I rulesfile if .I -f is provided, if neither is provided they will be read from stdin. .NH Walking, opening and reading. .PP .I Shifs keeps track of walk operations, when a .I fid is opened the full path is matched against each rule, if a rule matches a new process is spawned that sets its stdout to a pipe from where the subsequent read operations will feed and then executes the contents of the associated action. .NH Uses .PP Some of the tasks where shifs can be helpful are: performing simple transformations to the contents of arbitrary file trees, for example when importing a file system from a windows system one can easily transform all files to use the Plan 9/Unix new line format by simply using .I tr(1) . Other useful task is to format data from its canonical format into formats convenient for export, a good example of this is adding html formatting before exporting a file tree over httpd. Another possibility is to use it as replacement for .I exportfs that allows more fine grained control of not only what files are exported, but for example filter out part of the content by simply using .I grep .I -v . One can easily log all file access to a file tree by exporting it thru shifs: \" .1C .KF .P1 % shifs -o -r /lib/ '~ { echo `{date} - $FPATH > /tmp/access.log; cat $FPATH }' % cat /mnt/shifs/ndb/local > /dev/null % cat /tmp/access.log Wed Nov 15 14:58:52 CET 2006 - /ndb/local .P2 .ce .I "Figure 4. A way to log access to a file tree" .KE .PP Also it can be convenient to create synthetic files that collect and summarize the contents of whole file trees. Finally one can even create completely synthetic file trees, for example here is a file server that calculates the square of any given number: \" .1C .KF .P1 % shifs '~^[0-9]+$~ {load expr; echo ${expr $FNAME $FNAME x}}' % cat /mnt/shifs/4 16 % .P2 .ce .I "Figure 5. A simple squarefs" .KE .PP .NH Conclusions and future directions .PP The current version of .I shifs is still very much a prototype with many rough edges, but so far it has demonstrated to be a good tool to experiment with 'one off' file servers. And that is probably its greatest power, just like shells allow you to easily write small throw-away programs that when found useful can be codified either as shell scripts or in some cases rewritten in C. It also manages to at least partially succeed in its other goal of making the more traditional Unix/Plan 9 set of text manipulation tools more easily accessible when writing simple file servers. .I Shifs is still somewhat fragile, but still can be useful in experimenting with changes to the interface of existing file servers and working as an adaptor between file system interfaces. The main areas that still need work is handling of write operations and transformation of directory listings. The ruleset language is probably somewhat simplistic and naive and might need some redesign. Perhaps for better integration with a Plan 9 environment a rewrite in C could be considered, but maybe it would be best to instead try to take advantage of the "native" Dis. .NH Acknowledgements .PP Awk is clearly the main source of inspiration, but the more general tool philosophy underlines the goals of the project. Also one must acknowledge how both Limbo and the sh module in Inferno made implementation almost trivial. .PP I am not aware at the moment of any similar projects, but it is very likely that someone has thought of a similar thing before, my apologies if I have not noticed it. .NH References .LP [Inferno] Inferno Manual page for Sh(1) .LP [Aho79] A. V. Aho and B. W. Kernighan and P. J. Weinberger ``AWK - A Pattern Scanning and Processing Language'', .LP [Kernighan76] B. W. Kernighan and P. J. Plauger ``Software Tools''