Provide a statfs implementation, so df doesn't error out.

Change-Id: I5036cb41afebd310c3314b1eb54550f1280202c7
diff --git a/cache/cache.go b/cache/cache.go
index b76575f..f5cdaf4 100644
--- a/cache/cache.go
+++ b/cache/cache.go
@@ -27,6 +27,8 @@
 	Git  *gitCache
 	Tree *TreeCache
 	Blob *CAS
+
+	root string
 }
 
 // Options defines configurable options for the different caches.
@@ -65,5 +67,10 @@
 		return nil, err
 	}
 
-	return &Cache{Git: g, Tree: t, Blob: c}, nil
+	return &Cache{Git: g, Tree: t, Blob: c,
+		root: d,
+	}, nil
 }
+
+// Root returns the directory holding the cache storage.
+func (c *Cache) Root() string { return c.root }
diff --git a/fs/multifs.go b/fs/multifs.go
index b738de2..d40d567 100644
--- a/fs/multifs.go
+++ b/fs/multifs.go
@@ -20,6 +20,7 @@
 	"os"
 	"path/filepath"
 	"sync"
+	"syscall"
 
 	"github.com/google/slothfs/cache"
 	"github.com/google/slothfs/gitiles"
@@ -37,6 +38,24 @@
 	gitiles   *gitiles.Service
 }
 
+func (r *multiManifestFSRoot) StatFs() *fuse.StatfsOut {
+	var s syscall.Statfs_t
+	err := syscall.Statfs(r.cache.Root(), &s)
+	if err == nil {
+		return &fuse.StatfsOut{
+			Blocks:  s.Blocks,
+			Bsize:   uint32(s.Bsize),
+			Bfree:   s.Bfree,
+			Bavail:  s.Bavail,
+			Files:   s.Files,
+			Ffree:   s.Ffree,
+			Frsize:  uint32(s.Frsize),
+			NameLen: uint32(s.Namelen),
+		}
+	}
+	return nil
+}
+
 func (c *configNode) configureWorkspaces() error {
 	if c.root.options.ManifestDir == "" {
 		return nil