You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fusego/samples/roloopbackfs/roloopbackfs.go

203 lines
4.6 KiB
Go

// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package roloopbackfs
import (
"golang.org/x/net/context"
"log"
"os"
"sync"
"github.com/jacobsa/fuse"
"github.com/jacobsa/fuse/fuseops"
"github.com/jacobsa/fuse/fuseutil"
)
type readonlyLoopbackFs struct {
fuseutil.NotImplementedFileSystem
loopbackPath string
inodes *sync.Map
logger *log.Logger
}
var _ fuseutil.FileSystem = &readonlyLoopbackFs{}
// Create a file system that mirrors an existing physical path, in a readonly mode
func NewReadonlyLoopbackServer(loopbackPath string, logger *log.Logger) (server fuse.Server, err error) {
if _, err = os.Stat(loopbackPath); err != nil {
return nil, err
}
inodes := &sync.Map{}
root := &inodeEntry{
id: fuseops.RootInodeID,
path: loopbackPath,
}
inodes.Store(root.Id(), root)
server = fuseutil.NewFileSystemServer(&readonlyLoopbackFs{
loopbackPath: loopbackPath,
inodes: inodes,
logger: logger,
})
return
}
func (fs *readonlyLoopbackFs) StatFS(
ctx context.Context,
op *fuseops.StatFSOp) error {
return nil
}
func (fs *readonlyLoopbackFs) LookUpInode(
ctx context.Context,
op *fuseops.LookUpInodeOp) error {
entry, err := getOrCreateInode(fs.inodes, op.Parent, op.Name)
if err != nil {
fs.logger.Printf("fs.LookUpInode for '%v' on '%v': %v", entry, op.Name, err)
return fuse.EIO
}
if entry == nil {
return fuse.ENOENT
}
outputEntry := &op.Entry
outputEntry.Child = entry.Id()
attributes, err := entry.Attributes()
if err != nil {
fs.logger.Printf("fs.LookUpInode.Attributes for '%v' on '%v': %v", entry, op.Name, err)
return fuse.EIO
}
outputEntry.Attributes = *attributes
return nil
}
func (fs *readonlyLoopbackFs) GetInodeAttributes(
ctx context.Context,
op *fuseops.GetInodeAttributesOp) error {
var entry, found = fs.inodes.Load(op.Inode)
if !found {
return fuse.ENOENT
}
attributes, err := entry.(Inode).Attributes()
if err != nil {
fs.logger.Printf("fs.GetInodeAttributes for '%v': %v", entry, err)
return fuse.EIO
}
op.Attributes = *attributes
return nil
}
func (fs *readonlyLoopbackFs) OpenDir(
ctx context.Context,
op *fuseops.OpenDirOp) error {
// Allow opening any directory.
return nil
}
func (fs *readonlyLoopbackFs) ReadDir(
ctx context.Context,
op *fuseops.ReadDirOp) error {
var entry, found = fs.inodes.Load(op.Inode)
if !found {
return fuse.ENOENT
}
children, err := entry.(Inode).ListChildren(fs.inodes)
if err != nil {
fs.logger.Printf("fs.ReadDir for '%v': %v", entry, err)
return fuse.EIO
}
if op.Offset > fuseops.DirOffset(len(children)) {
return fuse.EIO
}
children = children[op.Offset:]
for _, child := range children {
bytesWritten := fuseutil.WriteDirent(op.Dst[op.BytesRead:], *child)
if bytesWritten == 0 {
break
}
op.BytesRead += bytesWritten
}
return nil
}
func (fs *readonlyLoopbackFs) OpenFile(
ctx context.Context,
op *fuseops.OpenFileOp) error {
// Allow opening any file.
return nil
}
func (fs *readonlyLoopbackFs) ReadFile(
ctx context.Context,
op *fuseops.ReadFileOp) error {
var entry, found = fs.inodes.Load(op.Inode)
if !found {
return fuse.ENOENT
}
contents, err := entry.(Inode).Contents()
if err != nil {
fs.logger.Printf("fs.ReadFile for '%v': %v", entry, err)
return fuse.EIO
}
if op.Offset > int64(len(contents)) {
return fuse.EIO
}
contents = contents[op.Offset:]
op.BytesRead = copy(op.Dst, contents)
return nil
}
func (fs *readonlyLoopbackFs) ReleaseDirHandle(
ctx context.Context,
op *fuseops.ReleaseDirHandleOp) error {
return nil
}
func (fs *readonlyLoopbackFs) GetXattr(
ctx context.Context,
op *fuseops.GetXattrOp) error {
return nil
}
func (fs *readonlyLoopbackFs) ListXattr(
ctx context.Context,
op *fuseops.ListXattrOp) error {
return nil
}
func (fs *readonlyLoopbackFs) ForgetInode(
ctx context.Context,
op *fuseops.ForgetInodeOp) error {
return nil
}
func (fs *readonlyLoopbackFs) ReleaseFileHandle(
ctx context.Context,
op *fuseops.ReleaseFileHandleOp) error {
return nil
}
func (fs *readonlyLoopbackFs) FlushFile(
ctx context.Context,
op *fuseops.FlushFileOp) error {
return nil
}