Skip to content

Commit

Permalink
Added support for symlinks in package fuse.
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobsa committed May 19, 2015
2 parents 1d03f16 + caca93f commit 9a62061
Show file tree
Hide file tree
Showing 7 changed files with 475 additions and 161 deletions.
16 changes: 16 additions & 0 deletions fuseops/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ func Convert(
io = to
co = &to.commonOp

case *bazilfuse.SymlinkRequest:
to := &CreateSymlinkOp{
Parent: InodeID(typed.Header.Node),
Name: typed.NewName,
Target: typed.Target,
}
io = to
co = &to.commonOp

case *bazilfuse.RemoveRequest:
if typed.Dir {
to := &RmDirOp{
Expand Down Expand Up @@ -217,6 +226,13 @@ func Convert(
io = to
co = &to.commonOp

case *bazilfuse.ReadlinkRequest:
to := &ReadSymlinkOp{
Inode: InodeID(typed.Header.Node),
}
io = to
co = &to.commonOp

default:
to := &unknownOp{}
io = to
Expand Down
70 changes: 66 additions & 4 deletions fuseops/ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,47 @@ func (o *CreateFileOp) toBazilfuseResponse() (bfResp interface{}) {
return
}

// Create a symlink inode.
type CreateSymlinkOp struct {
commonOp

// The ID of parent directory inode within which to create the child symlink.
Parent InodeID

// The name of the symlink to create.
Name string

// The target of the symlink.
Target string

// Set by the file system: information about the symlink inode that was
// created.
//
// The lookup count for the inode is implicitly incremented. See notes on
// ForgetInodeOp for more information.
Entry ChildInodeEntry
}

func (o *CreateSymlinkOp) ShortDesc() (desc string) {
desc = fmt.Sprintf(
"CreateSymlink(parent=%v, name=%q, target=%q)",
o.Parent,
o.Name,
o.Target)

return
}

func (o *CreateSymlinkOp) toBazilfuseResponse() (bfResp interface{}) {
resp := bazilfuse.SymlinkResponse{}
bfResp = &resp

convertChildInodeEntry(&o.Entry, &resp.LookupResponse)

return
return
}

////////////////////////////////////////////////////////////////////////
// Unlinking
////////////////////////////////////////////////////////////////////////
Expand All @@ -395,15 +436,16 @@ func (o *RmDirOp) toBazilfuseResponse() (bfResp interface{}) {
return
}

// Unlink a file from its parent. If this brings the inode's link count to
// zero, the inode should be deleted once the kernel sends ForgetInodeOp. It
// may still be referenced before then if a user still has the file open.
// Unlink a file or symlink from its parent. If this brings the inode's link
// count to zero, the inode should be deleted once the kernel sends
// ForgetInodeOp. It may still be referenced before then if a user still has
// the file open.
//
// Sample implementation in ext2: ext2_unlink (http://goo.gl/hY6r6C)
type UnlinkOp struct {
commonOp

// The ID of parent directory inode, and the name of the file being removed
// The ID of parent directory inode, and the name of the entry being removed
// within it.
Parent InodeID
Name string
Expand Down Expand Up @@ -844,3 +886,23 @@ type unknownOp struct {
func (o *unknownOp) toBazilfuseResponse() (bfResp interface{}) {
panic(fmt.Sprintf("Should never get here for unknown op: %s", o.ShortDesc()))
}

////////////////////////////////////////////////////////////////////////
// Reading symlinks
////////////////////////////////////////////////////////////////////////

// Read the target of a symlink inode.
type ReadSymlinkOp struct {
commonOp

// The symlink inode that we are reading.
Inode InodeID

// Set by the file system: the target of the symlink.
Target string
}

func (o *ReadSymlinkOp) toBazilfuseResponse() (bfResp interface{}) {
bfResp = o.Target
return
}
8 changes: 8 additions & 0 deletions fuseutil/file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type FileSystem interface {
ForgetInode(*fuseops.ForgetInodeOp)
MkDir(*fuseops.MkDirOp)
CreateFile(*fuseops.CreateFileOp)
CreateSymlink(*fuseops.CreateSymlinkOp)
RmDir(*fuseops.RmDirOp)
Unlink(*fuseops.UnlinkOp)
OpenDir(*fuseops.OpenDirOp)
Expand All @@ -56,6 +57,7 @@ type FileSystem interface {
SyncFile(*fuseops.SyncFileOp)
FlushFile(*fuseops.FlushFileOp)
ReleaseFileHandle(*fuseops.ReleaseFileHandleOp)
ReadSymlink(*fuseops.ReadSymlinkOp)
}

// Create a fuse.Server that handles ops by calling the associated FileSystem
Expand Down Expand Up @@ -149,6 +151,9 @@ func (s fileSystemServer) handleOp(op fuseops.Op) {
case *fuseops.CreateFileOp:
s.fs.CreateFile(typed)

case *fuseops.CreateSymlinkOp:
s.fs.CreateSymlink(typed)

case *fuseops.RmDirOp:
s.fs.RmDir(typed)

Expand Down Expand Up @@ -181,5 +186,8 @@ func (s fileSystemServer) handleOp(op fuseops.Op) {

case *fuseops.ReleaseFileHandleOp:
s.fs.ReleaseFileHandle(typed)

case *fuseops.ReadSymlinkOp:
s.fs.ReadSymlink(typed)
}
}
10 changes: 10 additions & 0 deletions fuseutil/not_implemented_file_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ func (fs *NotImplementedFileSystem) CreateFile(
op.Respond(fuse.ENOSYS)
}

func (fs *NotImplementedFileSystem) CreateSymlink(
op *fuseops.CreateSymlinkOp) {
op.Respond(fuse.ENOSYS)
}

func (fs *NotImplementedFileSystem) RmDir(
op *fuseops.RmDirOp) {
op.Respond(fuse.ENOSYS)
Expand Down Expand Up @@ -117,3 +122,8 @@ func (fs *NotImplementedFileSystem) ReleaseFileHandle(
op *fuseops.ReleaseFileHandleOp) {
op.Respond(fuse.ENOSYS)
}

func (fs *NotImplementedFileSystem) ReadSymlink(
op *fuseops.ReadSymlinkOp) {
op.Respond(fuse.ENOSYS)
}
Loading

0 comments on commit 9a62061

Please sign in to comment.