CS137 Homework 1: Hello, World!

Overview

The purpose of this assignment is to get you familiar with FUSE. You will be writing a very simple pseudo-filesystem that duplicates and slightly extends the "Hello, world" example on the FUSE Web site. The extension is that the single file in your filesystem will not be read-only; instead, you will be able to write a short replacement message to your "hello" file.

You may write in any language that is supported on Knuth and that supports Fuse, but as mentioned in class, I strongly recommend C or C++. Your code will be tested on Knuth and must compile and run there.

There are two ways to approach this assignment. The first is the lazy way: start with the hello.c example and make the quite minimal modifications needed to turn it into the required program. This is the foolish way to attack the problem.

The slightly more effortful, and much wiser, approach is to start with the more complex passthrough.c and use hello.c as a guide, implementing stubs for all the functions that aren't needed in your simple program. In the process, you will familiarize yourself with much more of Fuse, learn how to return errors, and develop a framework that will be useful when you do Homework 2. To compile passthrough.c, you'll also need passthrough_helpers.h.

The Assignment

Your assignment is to develop a filesystem with the following characteristics:

  1. There is a single file, with a name of your choice. (I'll use "goodgeoff" as an example.)
  2. ls and ls -l work on the root directory, and return plausible values for ".", "..", and "goodgeoff". The length for the latter should be correct, even after it has been modified.
  3. When read, "goodgeoff" (or whatever your file is called) initially contains a short string of your choosing (e.g, "Good Geoff!"). For cosmetic reasons, it should be terminated by a newline, but should not include a trailing null byte. If a write has been done, "goodgeoff" should contain the data written (see below).
  4. When written, "goodgeoff" should accept a number of bytes up to the length of the original string. (This length restriction is just to make your life easier; you are welcome to get fancier.) A write longer than the original length can be rejected with an appropriate error code, can be silently accepted up to the original length, or can extend the string. (Note that implementing write correctly requires that you also implement truncate.)
  5. Other operations are up to you. If you take the non-lazy approach, anything unimplemented should return an error code; I recommend ENOSYS. (The complete list of error codes can be found in /usr/include/asm-generic/errno*.h; I recommend sticking with the ones below about 50.)

Practical Details

You can do your development on any machine you choose that supports FUSE 3; however, your final code will be tested on Knuth and must run there. Mac users should use OSXFUSE; Linux users should be able to find FUSE 3 as part of their distribution.

FUSE is provided primarily as a library. Your program will link with that library to access FUSE Functions. Compiling and building the library yourself is not recommended.

Finding Example Code

Annoyingly, the sample FUSE code is only distributed as part of the entire source package. You can download the sources either by cloning the repository from Github, or by unpacking a tar file. Cloning is a bit simpler but involves a (very) slight risk that you'll get a broken example, because you're grabbing the "bleeding edge" version and it's possible that somebody just made an untested change. The instructions in this section are written for Linux users. If you want to work on a Mac, you'll need to adapt them for OSXFUSE, which shouldn't be too difficult. Windows users will need to adapt a bit further. Of course the best thing to do is to work on Knuth (which uses the same user name and password as your account on Wilkes). Because the examples are only part of the package, the instructions below include commands to get rid of the parts you don't want.

Unpacking a tar file (recommended)

You can get the latest official FUSE release from a tar file. To do so, go to the official release page and download the fuse-X.Y.Z.tar.xz file, where X.Y.Z is the latest release (3.12.0 as of this writing). Create and cd into a directory that will hold your examples, and move the .tar.xz file into that directory. Then run these commands (replacing X.Y.Z with the proper release ID, such as 3.12.0):

tar xvJf fuse-X.Y.Z.tar.xz
mv fuse-X.Y.Z/example .
rm -rf fuse-X.Y.Z*
You will now have a directory named "example" and nothing else. All the examples are in that directory.

Cloning

Alternatively, you can get the examples by cloning. First create a directory to work in, and cd into that directory. Then type:

git clone https://github.com/libfuse/libfuse.git
mv libfuse/example .
rm -rf libfuse
You will now have a directory named "examples" and nothing else. All the examples are in that directory.

A Note on Compiling FUSE Filesystems

Compiling a FUSE program requires a slightly complicated command:

gcc -g -Og `pkg-config fuse3 --cflags --libs` my_hello.c -o my_hello
A better approach, of course, is to use make. I have provided a truly minimal Makefile that will let you type "make foo" for any foo.c. You are encouraged to use it and extend it to be more sensible.

Writing the Code

Writing a Fuse client is complex enough to be worth a separate Web page with reference materials.

A minor glitch is that there are two versions of Fuse: Fuse2 and Fuse3. We will, of course, use the newest version.

Running & Testing

The class FUSE documentation page contains instructions on how to run and debug FUSE programs in general. For this assignment, be sure to test not only that you can read your file, but that you can write to it and that you get back precisely what you wrote. I suggest a command such as "echo wowee > testdir/hello" for writing the file. Depending on your shell settings you may need to use "echo wowee >! testdir/hello" (zsh, which is probably what you are using) or "echo wowee >| testdir/hello" (bash) to avoid a "file exists" or "cannot overwrite existing file" error message. When you get past simple testing, Prof. Kampe has kindly provided a Bash script that will conduct more expansive tests. The simplest invocation is just this:

bash hello_test.sh ./hello
If you've been creative with any naming, the full invocation is:

bash hello_test.sh my_hello "Hi there" howdy

which says that the executable file for your filesystem is "my_hello", its default contents are "Hi there", and the fake file inside the filesystem is named howdy.

Submission

Submit your code (it should be a single file) by running the cs137submit command (type "man submit" for more information). If you implement any additional features, describe them prominently in comments at the top of the file.


© 2022, Geoff Kuenning

This page is maintained by Geoff Kuenning.