diff options
Diffstat (limited to 'internal/fusefrontend_reverse/rfs.go')
-rw-r--r-- | internal/fusefrontend_reverse/rfs.go | 113 |
1 files changed, 64 insertions, 49 deletions
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 3243dfd..d07971a 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -3,8 +3,7 @@ package fusefrontend_reverse import ( "fmt" "os" - "path" - "strings" + "path/filepath" "syscall" "github.com/hanwen/go-fuse/fuse" @@ -50,47 +49,59 @@ func NewFS(args fusefrontend.Args) *reverseFS { } } -func (rfs *reverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { - // Handle gocryptfs.diriv - if relPath == nametransform.DirIVFilename || - strings.HasSuffix(relPath, nametransform.DirIVFilename) { - - fmt.Printf("Handling gocryptfs.diriv\n") - - cDir := path.Dir(relPath) - if cDir == "." { - cDir = "" - } - dir, err := rfs.decryptPath(cDir) - if err != nil { - fmt.Printf("decrypt err %q\n", cDir) - return nil, fuse.ToStatus(err) - } - // Does the parent dir exist? - a, status := rfs.loopbackfs.GetAttr(dir, context) - if !status.Ok() { - fmt.Printf("missing parent\n") - return nil, status - } - // Is it a dir at all? - if !a.IsDir() { - fmt.Printf("not isdir\n") - return nil, fuse.ENOTDIR - } - // Does the user have execute permissions? - if a.Mode&syscall.S_IXUSR == 0 { - fmt.Printf("not exec") - return nil, fuse.EPERM - } - // All good. Let's fake the file. - // We use the inode number of the parent dir (can this cause problems?). - a.Mode = DirIVMode - a.Size = nametransform.DirIVLen - a.Nlink = 1 - - return a, fuse.OK +// relDir is identical to filepath.Dir excepts that it returns "" when +// filepath.Dir would return ".". +// In the FUSE API, the root directory is called "", and we actually want that. +func relDir(path string) string { + dir := filepath.Dir(path) + if dir == "." { + return "" + } + return dir +} + +// dirIVAttr handles GetAttr requests for the virtual gocryptfs.diriv files. +func (rfs *reverseFS) dirIVAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { + cDir := relDir(relPath) + dir, err := rfs.decryptPath(cDir) + if err != nil { + fmt.Printf("decrypt err %q\n", cDir) + return nil, fuse.ToStatus(err) + } + // Does the parent dir exist? + a, status := rfs.loopbackfs.GetAttr(dir, context) + if !status.Ok() { + fmt.Printf("missing parent\n") + return nil, status + } + // Is it a dir at all? + if !a.IsDir() { + fmt.Printf("not isdir\n") + return nil, fuse.ENOTDIR + } + // Does the user have execute permissions? + if a.Mode&syscall.S_IXUSR == 0 { + fmt.Printf("not exec") + return nil, fuse.EPERM } + // All good. Let's fake the file. + // We use the inode number of the parent dir (can this cause problems?). + a.Mode = DirIVMode + a.Size = nametransform.DirIVLen + a.Nlink = 1 + return a, fuse.OK +} + +// isDirIV determines if the path points to a gocryptfs.diriv file +func isDirIV(relPath string) bool { + return filepath.Base(relPath) == nametransform.DirIVFilename +} + +func (rfs *reverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { + if isDirIV(relPath) { + return rfs.dirIVAttr(relPath, context) + } if rfs.isFiltered(relPath) { return nil, fuse.EPERM } @@ -110,17 +121,23 @@ func (rfs *reverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr } func (rfs *reverseFS) Access(relPath string, mode uint32, context *fuse.Context) fuse.Status { + if isDirIV(relPath) { + return fuse.OK + } if rfs.isFiltered(relPath) { return fuse.EPERM } - cPath, err := rfs.abs(rfs.encryptPath(relPath)) + absPath, err := rfs.abs(rfs.decryptPath(relPath)) if err != nil { return fuse.ToStatus(err) } - return fuse.ToStatus(syscall.Access(cPath, mode)) + return fuse.ToStatus(syscall.Access(absPath, mode)) } func (rfs *reverseFS) Open(relPath string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) { + if isDirIV(relPath) { + return NewDirIVFile(relPath) + } if rfs.isFiltered(relPath) { return nil, fuse.EPERM } @@ -135,8 +152,8 @@ func (rfs *reverseFS) Open(relPath string, flags uint32, context *fuse.Context) return NewFile(f, rfs.contentEnc) } -func (rfs *reverseFS) OpenDir(relPath string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { - relPath, err := rfs.decryptPath(relPath) +func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { + relPath, err := rfs.decryptPath(cipherPath) if err != nil { return nil, fuse.ToStatus(err) } @@ -146,11 +163,9 @@ func (rfs *reverseFS) OpenDir(relPath string, context *fuse.Context) ([]fuse.Dir return nil, status } // Encrypt names + dirIV := deriveDirIV(cipherPath) for i := range entries { - entries[i].Name, err = rfs.encryptPath(entries[i].Name) - if err != nil { - return nil, fuse.ToStatus(err) - } + entries[i].Name = rfs.nameTransform.EncryptName(entries[i].Name, dirIV) } // Add virtual gocryptfs.diriv entries = append(entries, fuse.DirEntry{syscall.S_IFREG | 0400, nametransform.DirIVFilename}) |