dep ensure
This commit is contained in:
parent
1158ac4760
commit
c8c18403e4
371 changed files with 168673 additions and 1 deletions
15
vendor/github.com/hanwen/go-fuse/AUTHORS
generated
vendored
Normal file
15
vendor/github.com/hanwen/go-fuse/AUTHORS
generated
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Adam H. Leventhal <adam.leventhal@gmail.com>
|
||||
Daniel Martà <mvdan@mvdan.cc>
|
||||
Fazlul Shahriar <fshahriar@gmail.com>
|
||||
Frederick Akalin <akalin@gmail.com>
|
||||
Google Inc.
|
||||
Haitao Li <lihaitao@gmail.com>
|
||||
Jakob Unterwurzacher <jakobunt@gmail.com>
|
||||
James D. Nurmi <james@abneptis.com>
|
||||
Jeff <leterip@me.com>
|
||||
Logan Hanks <logan@bitcasa.com>
|
||||
Nick Cooper <gh@smoogle.org>
|
||||
Patrick Crosby <pcrosby@gmail.com>
|
||||
Paul Jolly <paul@myitcv.org.uk>
|
||||
Valient Gough <vgough@pobox.com>
|
||||
Yongwoo Park <nnnlife@gmail.com>
|
||||
30
vendor/github.com/hanwen/go-fuse/LICENSE
generated
vendored
Normal file
30
vendor/github.com/hanwen/go-fuse/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// New BSD License
|
||||
//
|
||||
// Copyright (c) 2010 the Go-FUSE Authors. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Ivan Krasin nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
1
vendor/github.com/hanwen/go-fuse/fuse/.gitignore
generated
vendored
Normal file
1
vendor/github.com/hanwen/go-fuse/fuse/.gitignore
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
version.gen.go
|
||||
148
vendor/github.com/hanwen/go-fuse/fuse/api.go
generated
vendored
Normal file
148
vendor/github.com/hanwen/go-fuse/fuse/api.go
generated
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The fuse package provides APIs to implement filesystems in
|
||||
// userspace. Typically, each call of the API happens in its own
|
||||
// goroutine, so take care to make the file system thread-safe.
|
||||
|
||||
package fuse
|
||||
|
||||
// Types for users to implement.
|
||||
|
||||
// The result of Read is an array of bytes, but for performance
|
||||
// reasons, we can also return data as a file-descriptor/offset/size
|
||||
// tuple. If the backing store for a file is another filesystem, this
|
||||
// reduces the amount of copying between the kernel and the FUSE
|
||||
// server. The ReadResult interface captures both cases.
|
||||
type ReadResult interface {
|
||||
// Returns the raw bytes for the read, possibly using the
|
||||
// passed buffer. The buffer should be larger than the return
|
||||
// value from Size.
|
||||
Bytes(buf []byte) ([]byte, Status)
|
||||
|
||||
// Size returns how many bytes this return value takes at most.
|
||||
Size() int
|
||||
|
||||
// Done() is called after sending the data to the kernel.
|
||||
Done()
|
||||
}
|
||||
|
||||
type MountOptions struct {
|
||||
AllowOther bool
|
||||
|
||||
// Options are passed as -o string to fusermount.
|
||||
Options []string
|
||||
|
||||
// Default is _DEFAULT_BACKGROUND_TASKS, 12. This numbers
|
||||
// controls the allowed number of requests that relate to
|
||||
// async I/O. Concurrency for synchronous I/O is not limited.
|
||||
MaxBackground int
|
||||
|
||||
// Write size to use. If 0, use default. This number is
|
||||
// capped at the kernel maximum.
|
||||
MaxWrite int
|
||||
|
||||
// Max read ahead to use. If 0, use default. This number is
|
||||
// capped at the kernel maximum.
|
||||
MaxReadAhead int
|
||||
|
||||
// If IgnoreSecurityLabels is set, all security related xattr
|
||||
// requests will return NO_DATA without passing through the
|
||||
// user defined filesystem. You should only set this if you
|
||||
// file system implements extended attributes, and you are not
|
||||
// interested in security labels.
|
||||
IgnoreSecurityLabels bool // ignoring labels should be provided as a fusermount mount option.
|
||||
|
||||
// If given, use this buffer pool instead of the global one.
|
||||
Buffers BufferPool
|
||||
|
||||
// If RememberInodes is set, we will never forget inodes.
|
||||
// This may be useful for NFS.
|
||||
RememberInodes bool
|
||||
|
||||
// Values shown in "df -T" and friends
|
||||
// First column, "Filesystem"
|
||||
FsName string
|
||||
// Second column, "Type", will be shown as "fuse." + Name
|
||||
Name string
|
||||
|
||||
// If set, wrap the file system in a single-threaded locking wrapper.
|
||||
SingleThreaded bool
|
||||
|
||||
// If set, return ENOSYS for Getxattr calls, so the kernel does not issue any
|
||||
// Xattr operations at all.
|
||||
DisableXAttrs bool
|
||||
|
||||
// If set, print debugging information.
|
||||
Debug bool
|
||||
}
|
||||
|
||||
// RawFileSystem is an interface close to the FUSE wire protocol.
|
||||
//
|
||||
// Unless you really know what you are doing, you should not implement
|
||||
// this, but rather the FileSystem interface; the details of getting
|
||||
// interactions with open files, renames, and threading right etc. are
|
||||
// somewhat tricky and not very interesting.
|
||||
//
|
||||
// A null implementation is provided by NewDefaultRawFileSystem.
|
||||
type RawFileSystem interface {
|
||||
String() string
|
||||
|
||||
// If called, provide debug output through the log package.
|
||||
SetDebug(debug bool)
|
||||
|
||||
Lookup(header *InHeader, name string, out *EntryOut) (status Status)
|
||||
Forget(nodeid, nlookup uint64)
|
||||
|
||||
// Attributes.
|
||||
GetAttr(input *GetAttrIn, out *AttrOut) (code Status)
|
||||
SetAttr(input *SetAttrIn, out *AttrOut) (code Status)
|
||||
|
||||
// Modifying structure.
|
||||
Mknod(input *MknodIn, name string, out *EntryOut) (code Status)
|
||||
Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status)
|
||||
Unlink(header *InHeader, name string) (code Status)
|
||||
Rmdir(header *InHeader, name string) (code Status)
|
||||
Rename(input *RenameIn, oldName string, newName string) (code Status)
|
||||
Link(input *LinkIn, filename string, out *EntryOut) (code Status)
|
||||
|
||||
Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status)
|
||||
Readlink(header *InHeader) (out []byte, code Status)
|
||||
Access(input *AccessIn) (code Status)
|
||||
|
||||
// Extended attributes.
|
||||
GetXAttrSize(header *InHeader, attr string) (sz int, code Status)
|
||||
GetXAttrData(header *InHeader, attr string) (data []byte, code Status)
|
||||
ListXAttr(header *InHeader) (attributes []byte, code Status)
|
||||
SetXAttr(input *SetXAttrIn, attr string, data []byte) Status
|
||||
RemoveXAttr(header *InHeader, attr string) (code Status)
|
||||
|
||||
// File handling.
|
||||
Create(input *CreateIn, name string, out *CreateOut) (code Status)
|
||||
Open(input *OpenIn, out *OpenOut) (status Status)
|
||||
Read(input *ReadIn, buf []byte) (ReadResult, Status)
|
||||
|
||||
Flock(input *FlockIn, flags int) (code Status)
|
||||
|
||||
Release(input *ReleaseIn)
|
||||
Write(input *WriteIn, data []byte) (written uint32, code Status)
|
||||
Flush(input *FlushIn) Status
|
||||
Fsync(input *FsyncIn) (code Status)
|
||||
Fallocate(input *FallocateIn) (code Status)
|
||||
|
||||
// Directory handling
|
||||
OpenDir(input *OpenIn, out *OpenOut) (status Status)
|
||||
ReadDir(input *ReadIn, out *DirEntryList) Status
|
||||
ReadDirPlus(input *ReadIn, out *DirEntryList) Status
|
||||
ReleaseDir(input *ReleaseIn)
|
||||
FsyncDir(input *FsyncIn) (code Status)
|
||||
|
||||
//
|
||||
StatFs(input *InHeader, out *StatfsOut) (code Status)
|
||||
|
||||
// This is called on processing the first request. The
|
||||
// filesystem implementation can use the server argument to
|
||||
// talk back to the kernel (through notify methods).
|
||||
Init(*Server)
|
||||
}
|
||||
79
vendor/github.com/hanwen/go-fuse/fuse/attr.go
generated
vendored
Normal file
79
vendor/github.com/hanwen/go-fuse/fuse/attr.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (a *Attr) IsFifo() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFIFO }
|
||||
|
||||
// IsChar reports whether the FileInfo describes a character special file.
|
||||
func (a *Attr) IsChar() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFCHR }
|
||||
|
||||
// IsDir reports whether the FileInfo describes a directory.
|
||||
func (a *Attr) IsDir() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFDIR }
|
||||
|
||||
// IsBlock reports whether the FileInfo describes a block special file.
|
||||
func (a *Attr) IsBlock() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFBLK }
|
||||
|
||||
// IsRegular reports whether the FileInfo describes a regular file.
|
||||
func (a *Attr) IsRegular() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFREG }
|
||||
|
||||
// IsSymlink reports whether the FileInfo describes a symbolic link.
|
||||
func (a *Attr) IsSymlink() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFLNK }
|
||||
|
||||
// IsSocket reports whether the FileInfo describes a socket.
|
||||
func (a *Attr) IsSocket() bool { return (uint32(a.Mode) & syscall.S_IFMT) == syscall.S_IFSOCK }
|
||||
|
||||
func (a *Attr) SetTimes(access *time.Time, mod *time.Time, chstatus *time.Time) {
|
||||
if access != nil {
|
||||
a.Atime = uint64(access.Unix())
|
||||
a.Atimensec = uint32(access.Nanosecond())
|
||||
}
|
||||
if mod != nil {
|
||||
a.Mtime = uint64(mod.Unix())
|
||||
a.Mtimensec = uint32(mod.Nanosecond())
|
||||
}
|
||||
if chstatus != nil {
|
||||
a.Ctime = uint64(chstatus.Unix())
|
||||
a.Ctimensec = uint32(chstatus.Nanosecond())
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Attr) ChangeTime() time.Time {
|
||||
return time.Unix(int64(a.Ctime), int64(a.Ctimensec))
|
||||
}
|
||||
|
||||
func (a *Attr) AccessTime() time.Time {
|
||||
return time.Unix(int64(a.Atime), int64(a.Atimensec))
|
||||
}
|
||||
|
||||
func (a *Attr) ModTime() time.Time {
|
||||
return time.Unix(int64(a.Mtime), int64(a.Mtimensec))
|
||||
}
|
||||
|
||||
func ToStatT(f os.FileInfo) *syscall.Stat_t {
|
||||
s, _ := f.Sys().(*syscall.Stat_t)
|
||||
if s != nil {
|
||||
return s
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ToAttr(f os.FileInfo) *Attr {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
s := ToStatT(f)
|
||||
if s != nil {
|
||||
a := &Attr{}
|
||||
a.FromStat(s)
|
||||
return a
|
||||
}
|
||||
return nil
|
||||
}
|
||||
26
vendor/github.com/hanwen/go-fuse/fuse/attr_darwin.go
generated
vendored
Normal file
26
vendor/github.com/hanwen/go-fuse/fuse/attr_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (a *Attr) FromStat(s *syscall.Stat_t) {
|
||||
a.Ino = uint64(s.Ino)
|
||||
a.Size = uint64(s.Size)
|
||||
a.Blocks = uint64(s.Blocks)
|
||||
a.Atime = uint64(s.Atimespec.Sec)
|
||||
a.Atimensec = uint32(s.Atimespec.Nsec)
|
||||
a.Mtime = uint64(s.Mtimespec.Sec)
|
||||
a.Mtimensec = uint32(s.Mtimespec.Nsec)
|
||||
a.Ctime = uint64(s.Ctimespec.Sec)
|
||||
a.Ctimensec = uint32(s.Ctimespec.Nsec)
|
||||
a.Mode = uint32(s.Mode)
|
||||
a.Nlink = uint32(s.Nlink)
|
||||
a.Uid = uint32(s.Uid)
|
||||
a.Gid = uint32(s.Gid)
|
||||
a.Rdev = uint32(s.Rdev)
|
||||
}
|
||||
27
vendor/github.com/hanwen/go-fuse/fuse/attr_linux.go
generated
vendored
Normal file
27
vendor/github.com/hanwen/go-fuse/fuse/attr_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (a *Attr) FromStat(s *syscall.Stat_t) {
|
||||
a.Ino = uint64(s.Ino)
|
||||
a.Size = uint64(s.Size)
|
||||
a.Blocks = uint64(s.Blocks)
|
||||
a.Atime = uint64(s.Atim.Sec)
|
||||
a.Atimensec = uint32(s.Atim.Nsec)
|
||||
a.Mtime = uint64(s.Mtim.Sec)
|
||||
a.Mtimensec = uint32(s.Mtim.Nsec)
|
||||
a.Ctime = uint64(s.Ctim.Sec)
|
||||
a.Ctimensec = uint32(s.Ctim.Nsec)
|
||||
a.Mode = s.Mode
|
||||
a.Nlink = uint32(s.Nlink)
|
||||
a.Uid = uint32(s.Uid)
|
||||
a.Gid = uint32(s.Gid)
|
||||
a.Rdev = uint32(s.Rdev)
|
||||
a.Blksize = uint32(s.Blksize)
|
||||
}
|
||||
102
vendor/github.com/hanwen/go-fuse/fuse/bufferpool.go
generated
vendored
Normal file
102
vendor/github.com/hanwen/go-fuse/fuse/bufferpool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var paranoia bool
|
||||
|
||||
// BufferPool implements explicit memory management. It is used for
|
||||
// minimizing the GC overhead of communicating with the kernel.
|
||||
type BufferPool interface {
|
||||
// AllocBuffer creates a buffer of at least the given size. After use,
|
||||
// it should be deallocated with FreeBuffer().
|
||||
AllocBuffer(size uint32) []byte
|
||||
|
||||
// FreeBuffer takes back a buffer if it was allocated through
|
||||
// AllocBuffer. It is not an error to call FreeBuffer() on a slice
|
||||
// obtained elsewhere.
|
||||
FreeBuffer(slice []byte)
|
||||
}
|
||||
|
||||
type gcBufferPool struct {
|
||||
}
|
||||
|
||||
// NewGcBufferPool is a fallback to the standard allocation routines.
|
||||
func NewGcBufferPool() BufferPool {
|
||||
return &gcBufferPool{}
|
||||
}
|
||||
|
||||
func (p *gcBufferPool) AllocBuffer(size uint32) []byte {
|
||||
return make([]byte, size)
|
||||
}
|
||||
|
||||
func (p *gcBufferPool) FreeBuffer(slice []byte) {
|
||||
}
|
||||
|
||||
type bufferPoolImpl struct {
|
||||
lock sync.Mutex
|
||||
|
||||
// For each page size multiple a list of slice pointers.
|
||||
buffersBySize []*sync.Pool
|
||||
}
|
||||
|
||||
// NewBufferPool returns a BufferPool implementation that that returns
|
||||
// slices with capacity of a multiple of page size, which have possibly
|
||||
// been used, and may contain random contents. When using
|
||||
// NewBufferPool, file system handlers may not hang on to passed-in
|
||||
// buffers beyond the handler's return.
|
||||
func NewBufferPool() BufferPool {
|
||||
bp := new(bufferPoolImpl)
|
||||
return bp
|
||||
}
|
||||
|
||||
var pageSize = os.Getpagesize()
|
||||
|
||||
func (p *bufferPoolImpl) getPool(pageCount int) *sync.Pool {
|
||||
p.lock.Lock()
|
||||
for len(p.buffersBySize) < pageCount+1 {
|
||||
p.buffersBySize = append(p.buffersBySize, nil)
|
||||
}
|
||||
if p.buffersBySize[pageCount] == nil {
|
||||
p.buffersBySize[pageCount] = &sync.Pool{
|
||||
New: func() interface{} { return make([]byte, pageSize*pageCount) },
|
||||
}
|
||||
}
|
||||
pool := p.buffersBySize[pageCount]
|
||||
p.lock.Unlock()
|
||||
return pool
|
||||
}
|
||||
|
||||
func (p *bufferPoolImpl) AllocBuffer(size uint32) []byte {
|
||||
sz := int(size)
|
||||
if sz < pageSize {
|
||||
sz = pageSize
|
||||
}
|
||||
|
||||
if sz%pageSize != 0 {
|
||||
sz += pageSize
|
||||
}
|
||||
pages := sz / pageSize
|
||||
|
||||
b := p.getPool(pages).Get().([]byte)
|
||||
return b[:size]
|
||||
}
|
||||
|
||||
func (p *bufferPoolImpl) FreeBuffer(slice []byte) {
|
||||
if slice == nil {
|
||||
return
|
||||
}
|
||||
if cap(slice)%pageSize != 0 || cap(slice) == 0 {
|
||||
return
|
||||
}
|
||||
pages := cap(slice) / pageSize
|
||||
slice = slice[:cap(slice)]
|
||||
|
||||
p.getPool(pages).Put(slice)
|
||||
}
|
||||
35
vendor/github.com/hanwen/go-fuse/fuse/constants.go
generated
vendored
Normal file
35
vendor/github.com/hanwen/go-fuse/fuse/constants.go
generated
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
FUSE_ROOT_ID = 1
|
||||
|
||||
FUSE_UNKNOWN_INO = 0xffffffff
|
||||
|
||||
CUSE_UNRESTRICTED_IOCTL = (1 << 0)
|
||||
|
||||
FUSE_LK_FLOCK = (1 << 0)
|
||||
|
||||
FUSE_IOCTL_MAX_IOV = 256
|
||||
|
||||
FUSE_POLL_SCHEDULE_NOTIFY = (1 << 0)
|
||||
|
||||
CUSE_INIT_INFO_MAX = 4096
|
||||
|
||||
S_IFDIR = syscall.S_IFDIR
|
||||
S_IFREG = syscall.S_IFREG
|
||||
S_IFLNK = syscall.S_IFLNK
|
||||
S_IFIFO = syscall.S_IFIFO
|
||||
|
||||
CUSE_INIT = 4096
|
||||
|
||||
O_ANYWRITE = uint32(os.O_WRONLY | os.O_RDWR | os.O_APPEND | os.O_CREATE | os.O_TRUNC)
|
||||
)
|
||||
9
vendor/github.com/hanwen/go-fuse/fuse/constants_freebsd.go
generated
vendored
Normal file
9
vendor/github.com/hanwen/go-fuse/fuse/constants_freebsd.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
// arbitrary values
|
||||
const syscall_O_LARGEFILE = 1 << 29
|
||||
const syscall_O_NOATIME = 1 << 30
|
||||
12
vendor/github.com/hanwen/go-fuse/fuse/constants_linux.go
generated
vendored
Normal file
12
vendor/github.com/hanwen/go-fuse/fuse/constants_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const syscall_O_LARGEFILE = syscall.O_LARGEFILE
|
||||
const syscall_O_NOATIME = syscall.O_NOATIME
|
||||
156
vendor/github.com/hanwen/go-fuse/fuse/defaultraw.go
generated
vendored
Normal file
156
vendor/github.com/hanwen/go-fuse/fuse/defaultraw.go
generated
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// NewDefaultRawFileSystem returns ENOSYS (not implemented) for all
|
||||
// operations.
|
||||
func NewDefaultRawFileSystem() RawFileSystem {
|
||||
return (*defaultRawFileSystem)(nil)
|
||||
}
|
||||
|
||||
type defaultRawFileSystem struct{}
|
||||
|
||||
func (fs *defaultRawFileSystem) Init(*Server) {
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) String() string {
|
||||
return os.Args[0]
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) SetDebug(dbg bool) {
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) StatFs(header *InHeader, out *StatfsOut) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Lookup(header *InHeader, name string, out *EntryOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Forget(nodeID, nlookup uint64) {
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) GetAttr(input *GetAttrIn, out *AttrOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Open(input *OpenIn, out *OpenOut) (status Status) {
|
||||
return OK
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) SetAttr(input *SetAttrIn, out *AttrOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Readlink(header *InHeader) (out []byte, code Status) {
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Mknod(input *MknodIn, name string, out *EntryOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Unlink(header *InHeader, name string) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Rmdir(header *InHeader, name string) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Rename(input *RenameIn, oldName string, newName string) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Link(input *LinkIn, name string, out *EntryOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) GetXAttrSize(header *InHeader, attr string) (size int, code Status) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) GetXAttrData(header *InHeader, attr string) (data []byte, code Status) {
|
||||
return nil, ENOATTR
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) SetXAttr(input *SetXAttrIn, attr string, data []byte) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) ListXAttr(header *InHeader) (data []byte, code Status) {
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) RemoveXAttr(header *InHeader, attr string) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Access(input *AccessIn) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Create(input *CreateIn, name string, out *CreateOut) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) OpenDir(input *OpenIn, out *OpenOut) (status Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Status) {
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Flock(input *FlockIn, flags int) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Release(input *ReleaseIn) {
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Write(input *WriteIn, data []byte) (written uint32, code Status) {
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Flush(input *FlushIn) Status {
|
||||
return OK
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Fsync(input *FsyncIn) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) ReadDir(input *ReadIn, l *DirEntryList) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) ReadDirPlus(input *ReadIn, l *DirEntryList) Status {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) ReleaseDir(input *ReleaseIn) {
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) FsyncDir(input *FsyncIn) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultRawFileSystem) Fallocate(in *FallocateIn) (code Status) {
|
||||
return ENOSYS
|
||||
}
|
||||
102
vendor/github.com/hanwen/go-fuse/fuse/direntry.go
generated
vendored
Normal file
102
vendor/github.com/hanwen/go-fuse/fuse/direntry.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
// all of the code for DirEntryList.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var eightPadding [8]byte
|
||||
|
||||
const direntSize = int(unsafe.Sizeof(_Dirent{}))
|
||||
|
||||
// DirEntry is a type for PathFileSystem and NodeFileSystem to return
|
||||
// directory contents in.
|
||||
type DirEntry struct {
|
||||
// Mode is the file's mode. Only the high bits (eg. S_IFDIR)
|
||||
// are considered.
|
||||
Mode uint32
|
||||
|
||||
// Name is the basename of the file in the directory.
|
||||
Name string
|
||||
}
|
||||
|
||||
func (d DirEntry) String() string {
|
||||
return fmt.Sprintf("%o: %q", d.Mode, d.Name)
|
||||
}
|
||||
|
||||
// DirEntryList holds the return value for READDIR and READDIRPLUS
|
||||
// opcodes.
|
||||
type DirEntryList struct {
|
||||
buf []byte
|
||||
size int
|
||||
offset uint64
|
||||
}
|
||||
|
||||
// NewDirEntryList creates a DirEntryList with the given data buffer
|
||||
// and offset.
|
||||
func NewDirEntryList(data []byte, off uint64) *DirEntryList {
|
||||
return &DirEntryList{
|
||||
buf: data[:0],
|
||||
size: len(data),
|
||||
offset: off,
|
||||
}
|
||||
}
|
||||
|
||||
// AddDirEntry tries to add an entry, and reports whether it
|
||||
// succeeded.
|
||||
func (l *DirEntryList) AddDirEntry(e DirEntry) (bool, uint64) {
|
||||
return l.Add(0, e.Name, uint64(FUSE_UNKNOWN_INO), e.Mode)
|
||||
}
|
||||
|
||||
// Add adds a direntry to the DirEntryList, returning whether it
|
||||
// succeeded.
|
||||
func (l *DirEntryList) Add(prefix int, name string, inode uint64, mode uint32) (bool, uint64) {
|
||||
padding := (8 - len(name)&7) & 7
|
||||
delta := padding + direntSize + len(name) + prefix
|
||||
oldLen := len(l.buf)
|
||||
newLen := delta + oldLen
|
||||
|
||||
if newLen > l.size {
|
||||
return false, l.offset
|
||||
}
|
||||
l.buf = l.buf[:newLen]
|
||||
oldLen += prefix
|
||||
dirent := (*_Dirent)(unsafe.Pointer(&l.buf[oldLen]))
|
||||
dirent.Off = l.offset + 1
|
||||
dirent.Ino = inode
|
||||
dirent.NameLen = uint32(len(name))
|
||||
dirent.Typ = (mode & 0170000) >> 12
|
||||
oldLen += direntSize
|
||||
copy(l.buf[oldLen:], name)
|
||||
oldLen += len(name)
|
||||
|
||||
if padding > 0 {
|
||||
copy(l.buf[oldLen:], eightPadding[:padding])
|
||||
}
|
||||
|
||||
l.offset = dirent.Off
|
||||
return true, l.offset
|
||||
}
|
||||
|
||||
// AddDirLookupEntry is used for ReadDirPlus. It serializes a DirEntry
|
||||
// and returns the space for entry. If no space is left, returns a nil
|
||||
// pointer.
|
||||
func (l *DirEntryList) AddDirLookupEntry(e DirEntry) (*EntryOut, uint64) {
|
||||
lastStart := len(l.buf)
|
||||
ok, off := l.Add(int(unsafe.Sizeof(EntryOut{})), e.Name,
|
||||
uint64(FUSE_UNKNOWN_INO), e.Mode)
|
||||
if !ok {
|
||||
return nil, off
|
||||
}
|
||||
return (*EntryOut)(unsafe.Pointer(&l.buf[lastStart])), off
|
||||
}
|
||||
|
||||
func (l *DirEntryList) bytes() []byte {
|
||||
return l.buf
|
||||
}
|
||||
215
vendor/github.com/hanwen/go-fuse/fuse/lockingfs.go
generated
vendored
Normal file
215
vendor/github.com/hanwen/go-fuse/fuse/lockingfs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Locking raw FS.
|
||||
|
||||
type lockingRawFileSystem struct {
|
||||
RawFS RawFileSystem
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// Returns a Wrap
|
||||
func NewLockingRawFileSystem(fs RawFileSystem) RawFileSystem {
|
||||
return &lockingRawFileSystem{
|
||||
RawFS: fs,
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) FS() RawFileSystem {
|
||||
return fs.RawFS
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) locked() func() {
|
||||
fs.lock.Lock()
|
||||
return func() { fs.lock.Unlock() }
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Lookup(header *InHeader, name string, out *EntryOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Lookup(header, name, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) SetDebug(dbg bool) {
|
||||
defer fs.locked()()
|
||||
fs.RawFS.SetDebug(dbg)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Forget(nodeID uint64, nlookup uint64) {
|
||||
defer fs.locked()()
|
||||
fs.RawFS.Forget(nodeID, nlookup)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) GetAttr(input *GetAttrIn, out *AttrOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.GetAttr(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Open(input *OpenIn, out *OpenOut) (status Status) {
|
||||
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Open(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) SetAttr(input *SetAttrIn, out *AttrOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.SetAttr(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Readlink(header *InHeader) (out []byte, code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Readlink(header)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Mknod(input *MknodIn, name string, out *EntryOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Mknod(input, name, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Mkdir(input, name, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Unlink(header *InHeader, name string) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Unlink(header, name)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Rmdir(header *InHeader, name string) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Rmdir(header, name)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Symlink(header, pointedTo, linkName, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Rename(input *RenameIn, oldName string, newName string) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Rename(input, oldName, newName)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Link(input *LinkIn, name string, out *EntryOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Link(input, name, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) SetXAttr(input *SetXAttrIn, attr string, data []byte) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.SetXAttr(input, attr, data)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) GetXAttrData(header *InHeader, attr string) (data []byte, code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.GetXAttrData(header, attr)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) GetXAttrSize(header *InHeader, attr string) (sz int, code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.GetXAttrSize(header, attr)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) ListXAttr(header *InHeader) (data []byte, code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.ListXAttr(header)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) RemoveXAttr(header *InHeader, attr string) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.RemoveXAttr(header, attr)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Access(input *AccessIn) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Access(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Create(input *CreateIn, name string, out *CreateOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Create(input, name, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) OpenDir(input *OpenIn, out *OpenOut) (status Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.OpenDir(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Release(input *ReleaseIn) {
|
||||
defer fs.locked()()
|
||||
fs.RawFS.Release(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) ReleaseDir(input *ReleaseIn) {
|
||||
defer fs.locked()()
|
||||
fs.RawFS.ReleaseDir(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Read(input *ReadIn, buf []byte) (ReadResult, Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Read(input, buf)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Flock(input *FlockIn, flags int) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Flock(input, flags)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Write(input *WriteIn, data []byte) (written uint32, code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Write(input, data)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Flush(input *FlushIn) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Flush(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Fsync(input *FsyncIn) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Fsync(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) ReadDir(input *ReadIn, out *DirEntryList) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.ReadDir(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) ReadDirPlus(input *ReadIn, out *DirEntryList) Status {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.ReadDirPlus(input, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) FsyncDir(input *FsyncIn) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.FsyncDir(input)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Init(s *Server) {
|
||||
defer fs.locked()()
|
||||
fs.RawFS.Init(s)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) StatFs(header *InHeader, out *StatfsOut) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.StatFs(header, out)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) Fallocate(in *FallocateIn) (code Status) {
|
||||
defer fs.locked()()
|
||||
return fs.RawFS.Fallocate(in)
|
||||
}
|
||||
|
||||
func (fs *lockingRawFileSystem) String() string {
|
||||
defer fs.locked()()
|
||||
return fmt.Sprintf("Locked(%s)", fs.RawFS.String())
|
||||
}
|
||||
100
vendor/github.com/hanwen/go-fuse/fuse/misc.go
generated
vendored
Normal file
100
vendor/github.com/hanwen/go-fuse/fuse/misc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Random odds and ends.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func (code Status) String() string {
|
||||
if code <= 0 {
|
||||
return []string{
|
||||
"OK",
|
||||
"NOTIFY_POLL",
|
||||
"NOTIFY_INVAL_INODE",
|
||||
"NOTIFY_INVAL_ENTRY",
|
||||
"NOTIFY_INVAL_STORE",
|
||||
"NOTIFY_INVAL_RETRIEVE",
|
||||
"NOTIFY_INVAL_DELETE",
|
||||
}[-code]
|
||||
}
|
||||
return fmt.Sprintf("%d=%v", int(code), syscall.Errno(code))
|
||||
}
|
||||
|
||||
func (code Status) Ok() bool {
|
||||
return code == OK
|
||||
}
|
||||
|
||||
// ToStatus extracts an errno number from Go error objects. If it
|
||||
// fails, it logs an error and returns ENOSYS.
|
||||
func ToStatus(err error) Status {
|
||||
switch err {
|
||||
case nil:
|
||||
return OK
|
||||
case os.ErrPermission:
|
||||
return EPERM
|
||||
case os.ErrExist:
|
||||
return Status(syscall.EEXIST)
|
||||
case os.ErrNotExist:
|
||||
return ENOENT
|
||||
case os.ErrInvalid:
|
||||
return EINVAL
|
||||
}
|
||||
|
||||
switch t := err.(type) {
|
||||
case syscall.Errno:
|
||||
return Status(t)
|
||||
case *os.SyscallError:
|
||||
return Status(t.Err.(syscall.Errno))
|
||||
case *os.PathError:
|
||||
return ToStatus(t.Err)
|
||||
case *os.LinkError:
|
||||
return ToStatus(t.Err)
|
||||
}
|
||||
log.Println("can't convert error type:", err)
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func toSlice(dest *[]byte, ptr unsafe.Pointer, byteCount uintptr) {
|
||||
h := (*reflect.SliceHeader)(unsafe.Pointer(dest))
|
||||
*h = reflect.SliceHeader{
|
||||
Data: uintptr(ptr),
|
||||
Len: int(byteCount),
|
||||
Cap: int(byteCount),
|
||||
}
|
||||
}
|
||||
|
||||
func CurrentOwner() *Owner {
|
||||
return &Owner{
|
||||
Uid: uint32(os.Getuid()),
|
||||
Gid: uint32(os.Getgid()),
|
||||
}
|
||||
}
|
||||
|
||||
const _UTIME_OMIT = ((1 << 30) - 2)
|
||||
|
||||
// UtimeToTimespec converts a "Time" pointer as passed to Utimens to a
|
||||
// "Timespec" that can be passed to the utimensat syscall.
|
||||
// A nil pointer is converted to the special UTIME_OMIT value.
|
||||
func UtimeToTimespec(t *time.Time) (ts syscall.Timespec) {
|
||||
if t == nil {
|
||||
ts.Nsec = _UTIME_OMIT
|
||||
} else {
|
||||
ts = syscall.NsecToTimespec(t.UnixNano())
|
||||
// Go bug https://github.com/golang/go/issues/12777
|
||||
if ts.Nsec < 0 {
|
||||
ts.Nsec = 0
|
||||
}
|
||||
}
|
||||
return ts
|
||||
}
|
||||
82
vendor/github.com/hanwen/go-fuse/fuse/mount_darwin.go
generated
vendored
Normal file
82
vendor/github.com/hanwen/go-fuse/fuse/mount_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func openFUSEDevice() (*os.File, error) {
|
||||
fs, err := filepath.Glob("/dev/osxfuse*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(fs) == 0 {
|
||||
// TODO(hanwen): run the load_osxfuse command.
|
||||
return nil, fmt.Errorf("no FUSE devices found")
|
||||
}
|
||||
for _, fn := range fs {
|
||||
f, err := os.OpenFile(fn, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
return f, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("all FUSE devices busy")
|
||||
}
|
||||
|
||||
const oldMountBin = "/Library/Filesystems/osxfusefs.fs/Support/mount_osxfusefs"
|
||||
const newMountBin = "/Library/Filesystems/osxfuse.fs/Contents/Resources/mount_osxfuse"
|
||||
|
||||
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
|
||||
f, err := openFUSEDevice()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
bin := oldMountBin
|
||||
if _, err := os.Stat(newMountBin); err == nil {
|
||||
bin = newMountBin
|
||||
}
|
||||
|
||||
cmd := exec.Command(bin, "-o", strings.Join(opts.optionsStrings(), ","), "-o", fmt.Sprintf("iosize=%d", opts.MaxWrite), "3", mountPoint)
|
||||
cmd.ExtraFiles = []*os.File{f}
|
||||
cmd.Env = append(os.Environ(), "MOUNT_FUSEFS_CALL_BY_LIB=", "MOUNT_OSXFUSE_CALL_BY_LIB=",
|
||||
"MOUNT_OSXFUSE_DAEMON_PATH="+os.Args[0],
|
||||
"MOUNT_FUSEFS_DAEMON_PATH="+os.Args[0])
|
||||
|
||||
var out, errOut bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &errOut
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
f.Close()
|
||||
return 0, err
|
||||
}
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("mount_osxfusefs failed: %v. Stderr: %s, Stdout: %s", err, errOut.String(), out.String())
|
||||
}
|
||||
|
||||
ready <- err
|
||||
close(ready)
|
||||
}()
|
||||
|
||||
// The finalizer for f will close its fd so we return a dup.
|
||||
defer f.Close()
|
||||
return syscall.Dup(int(f.Fd()))
|
||||
}
|
||||
|
||||
func unmount(dir string) error {
|
||||
return syscall.Unmount(dir, 0)
|
||||
}
|
||||
162
vendor/github.com/hanwen/go-fuse/fuse/mount_linux.go
generated
vendored
Normal file
162
vendor/github.com/hanwen/go-fuse/fuse/mount_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func unixgramSocketpair() (l, r *os.File, err error) {
|
||||
fd, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
|
||||
if err != nil {
|
||||
return nil, nil, os.NewSyscallError("socketpair",
|
||||
err.(syscall.Errno))
|
||||
}
|
||||
l = os.NewFile(uintptr(fd[0]), "socketpair-half1")
|
||||
r = os.NewFile(uintptr(fd[1]), "socketpair-half2")
|
||||
return
|
||||
}
|
||||
|
||||
// Create a FUSE FS on the specified mount point. The returned
|
||||
// mount point is always absolute.
|
||||
func mount(mountPoint string, opts *MountOptions, ready chan<- error) (fd int, err error) {
|
||||
local, remote, err := unixgramSocketpair()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer local.Close()
|
||||
defer remote.Close()
|
||||
|
||||
bin, err := fusermountBinary()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
cmd := []string{bin, mountPoint}
|
||||
if s := opts.optionsStrings(); len(s) > 0 {
|
||||
cmd = append(cmd, "-o", strings.Join(s, ","))
|
||||
}
|
||||
proc, err := os.StartProcess(bin,
|
||||
cmd,
|
||||
&os.ProcAttr{
|
||||
Env: []string{"_FUSE_COMMFD=3"},
|
||||
Files: []*os.File{os.Stdin, os.Stdout, os.Stderr, remote}})
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w, err := proc.Wait()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !w.Success() {
|
||||
err = fmt.Errorf("fusermount exited with code %v\n", w.Sys())
|
||||
return
|
||||
}
|
||||
|
||||
fd, err = getConnection(local)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
close(ready)
|
||||
return fd, err
|
||||
}
|
||||
|
||||
func privilegedUnmount(mountPoint string) error {
|
||||
dir, _ := filepath.Split(mountPoint)
|
||||
bin, err := umountBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
proc, err := os.StartProcess(bin,
|
||||
[]string{bin, mountPoint},
|
||||
&os.ProcAttr{Dir: dir, Files: []*os.File{nil, nil, os.Stderr}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := proc.Wait()
|
||||
if !w.Success() {
|
||||
return fmt.Errorf("umount exited with code %v\n", w.Sys())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func unmount(mountPoint string) (err error) {
|
||||
if os.Geteuid() == 0 {
|
||||
return privilegedUnmount(mountPoint)
|
||||
}
|
||||
bin, err := fusermountBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
errBuf := bytes.Buffer{}
|
||||
cmd := exec.Command(bin, "-u", mountPoint)
|
||||
cmd.Stderr = &errBuf
|
||||
err = cmd.Run()
|
||||
if errBuf.Len() > 0 {
|
||||
return fmt.Errorf("%s (code %v)\n",
|
||||
errBuf.String(), err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func getConnection(local *os.File) (int, error) {
|
||||
var data [4]byte
|
||||
control := make([]byte, 4*256)
|
||||
|
||||
// n, oobn, recvflags, from, errno - todo: error checking.
|
||||
_, oobn, _, _,
|
||||
err := syscall.Recvmsg(
|
||||
int(local.Fd()), data[:], control[:], 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
message := *(*syscall.Cmsghdr)(unsafe.Pointer(&control[0]))
|
||||
fd := *(*int32)(unsafe.Pointer(uintptr(unsafe.Pointer(&control[0])) + syscall.SizeofCmsghdr))
|
||||
|
||||
if message.Type != 1 {
|
||||
return 0, fmt.Errorf("getConnection: recvmsg returned wrong control type: %d", message.Type)
|
||||
}
|
||||
if oobn <= syscall.SizeofCmsghdr {
|
||||
return 0, fmt.Errorf("getConnection: too short control message. Length: %d", oobn)
|
||||
}
|
||||
if fd < 0 {
|
||||
return 0, fmt.Errorf("getConnection: fd < 0: %d", fd)
|
||||
}
|
||||
return int(fd), nil
|
||||
}
|
||||
|
||||
// lookPathFallback - search binary in PATH and, if that fails,
|
||||
// in fallbackDir. This is useful if PATH is possible empty.
|
||||
func lookPathFallback(file string, fallbackDir string) (string, error) {
|
||||
binPath, err := exec.LookPath(file)
|
||||
if err == nil {
|
||||
return binPath, nil
|
||||
}
|
||||
|
||||
abs := path.Join(fallbackDir, file)
|
||||
return exec.LookPath(abs)
|
||||
}
|
||||
|
||||
func fusermountBinary() (string, error) {
|
||||
return lookPathFallback("fusermount", "/bin")
|
||||
}
|
||||
|
||||
func umountBinary() (string, error) {
|
||||
return lookPathFallback("umount", "/bin")
|
||||
}
|
||||
190
vendor/github.com/hanwen/go-fuse/fuse/nodefs/api.go
generated
vendored
Normal file
190
vendor/github.com/hanwen/go-fuse/fuse/nodefs/api.go
generated
vendored
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// The nodefs package offers a high level API that resembles the
|
||||
// kernel's idea of what an FS looks like. File systems can have
|
||||
// multiple hard-links to one file, for example. It is also suited if
|
||||
// the data to represent fits in memory: you can construct the
|
||||
// complete file system tree at mount time
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// The Node interface implements the user-defined file system
|
||||
// functionality
|
||||
type Node interface {
|
||||
// Inode and SetInode are basic getter/setters. They are
|
||||
// called by the FileSystemConnector. You get them for free by
|
||||
// embedding the result of NewDefaultNode() in your node
|
||||
// struct.
|
||||
Inode() *Inode
|
||||
SetInode(node *Inode)
|
||||
|
||||
// OnMount is called on the root node just after a mount is
|
||||
// executed, either when the actual root is mounted, or when a
|
||||
// filesystem is mounted in-process. The passed-in
|
||||
// FileSystemConnector gives access to Notify methods and
|
||||
// Debug settings.
|
||||
OnMount(conn *FileSystemConnector)
|
||||
|
||||
// OnUnmount is executed just before a submount is removed,
|
||||
// and when the process receives a forget for the FUSE root
|
||||
// node.
|
||||
OnUnmount()
|
||||
|
||||
// Lookup finds a child node to this node; it is only called
|
||||
// for directory Nodes.
|
||||
Lookup(out *fuse.Attr, name string, context *fuse.Context) (*Inode, fuse.Status)
|
||||
|
||||
// Deletable() should return true if this node may be discarded once
|
||||
// the kernel forgets its reference.
|
||||
// If it returns false, OnForget will never get called for this node. This
|
||||
// is appropriate if the filesystem has no persistent backing store
|
||||
// (in-memory filesystems) where discarding the node loses the stored data.
|
||||
// Deletable will be called from within the treeLock critical section, so you
|
||||
// cannot look at other nodes.
|
||||
Deletable() bool
|
||||
|
||||
// OnForget is called when the kernel forgets its reference to this node and
|
||||
// sends a FORGET request. It should perform cleanup and free memory as
|
||||
// appropriate for the filesystem.
|
||||
// OnForget is not called if the node is a directory and has children.
|
||||
// This is called from within a treeLock critical section.
|
||||
OnForget()
|
||||
|
||||
// Misc.
|
||||
Access(mode uint32, context *fuse.Context) (code fuse.Status)
|
||||
Readlink(c *fuse.Context) ([]byte, fuse.Status)
|
||||
|
||||
// Namespace operations; these are only called on directory Nodes.
|
||||
|
||||
// Mknod should create the node, add it to the receiver's
|
||||
// inode, and return it
|
||||
Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (newNode *Inode, code fuse.Status)
|
||||
|
||||
// Mkdir should create the directory Inode, add it to the
|
||||
// receiver's Inode, and return it
|
||||
Mkdir(name string, mode uint32, context *fuse.Context) (newNode *Inode, code fuse.Status)
|
||||
Unlink(name string, context *fuse.Context) (code fuse.Status)
|
||||
Rmdir(name string, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
// Symlink should create a child inode to the receiver, and
|
||||
// return it.
|
||||
Symlink(name string, content string, context *fuse.Context) (*Inode, fuse.Status)
|
||||
Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
// Link should return the Inode of the resulting link. In
|
||||
// a POSIX conformant file system, this should add 'existing'
|
||||
// to the receiver, and return the Inode corresponding to
|
||||
// 'existing'.
|
||||
Link(name string, existing Node, context *fuse.Context) (newNode *Inode, code fuse.Status)
|
||||
|
||||
// Create should return an open file, and the Inode for that file.
|
||||
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, child *Inode, code fuse.Status)
|
||||
|
||||
// Open opens a file, and returns a File which is associated
|
||||
// with a file handle. It is OK to return (nil, OK) here. In
|
||||
// that case, the Node should implement Read or Write
|
||||
// directly.
|
||||
Open(flags uint32, context *fuse.Context) (file File, code fuse.Status)
|
||||
OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status)
|
||||
Read(file File, dest []byte, off int64, context *fuse.Context) (fuse.ReadResult, fuse.Status)
|
||||
Write(file File, data []byte, off int64, context *fuse.Context) (written uint32, code fuse.Status)
|
||||
|
||||
// XAttrs
|
||||
GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status)
|
||||
RemoveXAttr(attr string, context *fuse.Context) fuse.Status
|
||||
SetXAttr(attr string, data []byte, flags int, context *fuse.Context) fuse.Status
|
||||
ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status)
|
||||
|
||||
// Attributes
|
||||
GetAttr(out *fuse.Attr, file File, context *fuse.Context) (code fuse.Status)
|
||||
Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status)
|
||||
Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status)
|
||||
Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status)
|
||||
Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status)
|
||||
Fallocate(file File, off uint64, size uint64, mode uint32, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
StatFs() *fuse.StatfsOut
|
||||
}
|
||||
|
||||
// A File object is returned from FileSystem.Open and
|
||||
// FileSystem.Create. Include the NewDefaultFile return value into
|
||||
// the struct to inherit a null implementation.
|
||||
type File interface {
|
||||
// Called upon registering the filehandle in the inode.
|
||||
SetInode(*Inode)
|
||||
|
||||
// The String method is for debug printing.
|
||||
String() string
|
||||
|
||||
// Wrappers around other File implementations, should return
|
||||
// the inner file here.
|
||||
InnerFile() File
|
||||
|
||||
Read(dest []byte, off int64) (fuse.ReadResult, fuse.Status)
|
||||
Write(data []byte, off int64) (written uint32, code fuse.Status)
|
||||
|
||||
Flock(flags int) fuse.Status
|
||||
|
||||
// Flush is called for close() call on a file descriptor. In
|
||||
// case of duplicated descriptor, it may be called more than
|
||||
// once for a file.
|
||||
Flush() fuse.Status
|
||||
|
||||
// This is called to before the file handle is forgotten. This
|
||||
// method has no return value, so nothing can synchronizes on
|
||||
// the call. Any cleanup that requires specific synchronization or
|
||||
// could fail with I/O errors should happen in Flush instead.
|
||||
Release()
|
||||
Fsync(flags int) (code fuse.Status)
|
||||
|
||||
// The methods below may be called on closed files, due to
|
||||
// concurrency. In that case, you should return EBADF.
|
||||
Truncate(size uint64) fuse.Status
|
||||
GetAttr(out *fuse.Attr) fuse.Status
|
||||
Chown(uid uint32, gid uint32) fuse.Status
|
||||
Chmod(perms uint32) fuse.Status
|
||||
Utimens(atime *time.Time, mtime *time.Time) fuse.Status
|
||||
Allocate(off uint64, size uint64, mode uint32) (code fuse.Status)
|
||||
}
|
||||
|
||||
// Wrap a File return in this to set FUSE flags. Also used internally
|
||||
// to store open file data.
|
||||
type WithFlags struct {
|
||||
File
|
||||
|
||||
// For debugging.
|
||||
Description string
|
||||
|
||||
// Put FOPEN_* flags here.
|
||||
FuseFlags uint32
|
||||
|
||||
// O_RDWR, O_TRUNCATE, etc.
|
||||
OpenFlags uint32
|
||||
}
|
||||
|
||||
// Options contains time out options for a node FileSystem. The
|
||||
// default copied from libfuse and set in NewMountOptions() is
|
||||
// (1s,1s,0s).
|
||||
type Options struct {
|
||||
EntryTimeout time.Duration
|
||||
AttrTimeout time.Duration
|
||||
NegativeTimeout time.Duration
|
||||
|
||||
// If set, replace all uids with given UID.
|
||||
// NewOptions() will set this to the daemon's
|
||||
// uid/gid.
|
||||
*fuse.Owner
|
||||
|
||||
// This option exists for compatibility and is ignored.
|
||||
PortableInodes bool
|
||||
|
||||
// If set, print debug information.
|
||||
Debug bool
|
||||
}
|
||||
75
vendor/github.com/hanwen/go-fuse/fuse/nodefs/defaultfile.go
generated
vendored
Normal file
75
vendor/github.com/hanwen/go-fuse/fuse/nodefs/defaultfile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
type defaultFile struct{}
|
||||
|
||||
// NewDefaultFile returns a File instance that returns ENOSYS for
|
||||
// every operation.
|
||||
func NewDefaultFile() File {
|
||||
return (*defaultFile)(nil)
|
||||
}
|
||||
|
||||
func (f *defaultFile) SetInode(*Inode) {
|
||||
}
|
||||
|
||||
func (f *defaultFile) InnerFile() File {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *defaultFile) String() string {
|
||||
return "defaultFile"
|
||||
}
|
||||
|
||||
func (f *defaultFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
return 0, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Flock(flags int) fuse.Status { return fuse.ENOSYS }
|
||||
func (f *defaultFile) Flush() fuse.Status {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *defaultFile) Release() {
|
||||
|
||||
}
|
||||
|
||||
func (f *defaultFile) GetAttr(*fuse.Attr) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Fsync(flags int) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Truncate(size uint64) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Chown(uid uint32, gid uint32) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Chmod(perms uint32) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (f *defaultFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
172
vendor/github.com/hanwen/go-fuse/fuse/nodefs/defaultnode.go
generated
vendored
Normal file
172
vendor/github.com/hanwen/go-fuse/fuse/nodefs/defaultnode.go
generated
vendored
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// NewDefaultNode returns an implementation of Node that returns
|
||||
// ENOSYS for all operations.
|
||||
func NewDefaultNode() Node {
|
||||
return &defaultNode{}
|
||||
}
|
||||
|
||||
type defaultNode struct {
|
||||
inode *Inode
|
||||
}
|
||||
|
||||
func (fs *defaultNode) OnUnmount() {
|
||||
}
|
||||
|
||||
func (fs *defaultNode) OnMount(conn *FileSystemConnector) {
|
||||
}
|
||||
|
||||
func (n *defaultNode) StatFs() *fuse.StatfsOut {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *defaultNode) SetInode(node *Inode) {
|
||||
n.inode = node
|
||||
}
|
||||
|
||||
func (n *defaultNode) Deletable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *defaultNode) Inode() *Inode {
|
||||
return n.inode
|
||||
}
|
||||
|
||||
func (n *defaultNode) OnForget() {
|
||||
}
|
||||
|
||||
func (n *defaultNode) Lookup(out *fuse.Attr, name string, context *fuse.Context) (node *Inode, code fuse.Status) {
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
|
||||
func (n *defaultNode) Access(mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
func (n *defaultNode) Mkdir(name string, mode uint32, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
func (n *defaultNode) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
func (n *defaultNode) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
func (n *defaultNode) Symlink(name string, content string, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Link(name string, existing Node, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, newNode *Inode, code fuse.Status) {
|
||||
return nil, nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Open(flags uint32, context *fuse.Context) (file File, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Flush(file File, openFlags uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) OpenDir(context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
|
||||
ch := n.Inode().Children()
|
||||
s := make([]fuse.DirEntry, 0, len(ch))
|
||||
for name, child := range ch {
|
||||
if child.mountPoint != nil {
|
||||
continue
|
||||
}
|
||||
var a fuse.Attr
|
||||
code := child.Node().GetAttr(&a, nil, context)
|
||||
if code.Ok() {
|
||||
s = append(s, fuse.DirEntry{Name: name, Mode: a.Mode})
|
||||
}
|
||||
}
|
||||
return s, fuse.OK
|
||||
}
|
||||
|
||||
func (n *defaultNode) GetXAttr(attribute string, context *fuse.Context) (data []byte, code fuse.Status) {
|
||||
return nil, fuse.ENOATTR
|
||||
}
|
||||
|
||||
func (n *defaultNode) RemoveXAttr(attr string, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) SetXAttr(attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) ListXAttr(context *fuse.Context) (attrs []string, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) GetAttr(out *fuse.Attr, file File, context *fuse.Context) (code fuse.Status) {
|
||||
if file != nil {
|
||||
return file.GetAttr(out)
|
||||
}
|
||||
if n.Inode().IsDir() {
|
||||
out.Mode = fuse.S_IFDIR | 0755
|
||||
} else {
|
||||
out.Mode = fuse.S_IFREG | 0644
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *defaultNode) Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Fallocate(file File, off uint64, size uint64, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Read(file File, dest []byte, off int64, context *fuse.Context) (fuse.ReadResult, fuse.Status) {
|
||||
if file != nil {
|
||||
return file.Read(dest, off)
|
||||
}
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (n *defaultNode) Write(file File, data []byte, off int64, context *fuse.Context) (written uint32, code fuse.Status) {
|
||||
if file != nil {
|
||||
return file.Write(data, off)
|
||||
}
|
||||
return 0, fuse.ENOSYS
|
||||
}
|
||||
118
vendor/github.com/hanwen/go-fuse/fuse/nodefs/dir.go
generated
vendored
Normal file
118
vendor/github.com/hanwen/go-fuse/fuse/nodefs/dir.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
type connectorDir struct {
|
||||
node Node
|
||||
rawFS fuse.RawFileSystem
|
||||
|
||||
// Protect stream and lastOffset. These are written in case
|
||||
// there is a seek on the directory.
|
||||
mu sync.Mutex
|
||||
stream []fuse.DirEntry
|
||||
|
||||
// lastOffset stores the last offset for a readdir. This lets
|
||||
// readdir pick up changes to the directory made after opening
|
||||
// it.
|
||||
lastOffset uint64
|
||||
}
|
||||
|
||||
func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.stream == nil {
|
||||
return fuse.OK
|
||||
}
|
||||
// rewinddir() should be as if reopening directory.
|
||||
// TODO - test this.
|
||||
if d.lastOffset > 0 && input.Offset == 0 {
|
||||
d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
if input.Offset > uint64(len(d.stream)) {
|
||||
// This shouldn't happen, but let's not crash.
|
||||
return fuse.EINVAL
|
||||
}
|
||||
|
||||
todo := d.stream[input.Offset:]
|
||||
for _, e := range todo {
|
||||
if e.Name == "" {
|
||||
log.Printf("got empty directory entry, mode %o.", e.Mode)
|
||||
continue
|
||||
}
|
||||
ok, off := out.AddDirEntry(e)
|
||||
d.lastOffset = off
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
if d.stream == nil {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
// rewinddir() should be as if reopening directory.
|
||||
if d.lastOffset > 0 && input.Offset == 0 {
|
||||
d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
}
|
||||
|
||||
if input.Offset > uint64(len(d.stream)) {
|
||||
// This shouldn't happen, but let's not crash.
|
||||
return fuse.EINVAL
|
||||
}
|
||||
todo := d.stream[input.Offset:]
|
||||
for _, e := range todo {
|
||||
if e.Name == "" {
|
||||
log.Printf("got empty directory entry, mode %o.", e.Mode)
|
||||
continue
|
||||
}
|
||||
|
||||
// we have to be sure entry will fit if we try to add
|
||||
// it, or we'll mess up the lookup counts.
|
||||
entryDest, off := out.AddDirLookupEntry(e)
|
||||
if entryDest == nil {
|
||||
break
|
||||
}
|
||||
entryDest.Ino = uint64(fuse.FUSE_UNKNOWN_INO)
|
||||
|
||||
// No need to fill attributes for . and ..
|
||||
if e.Name == "." || e.Name == ".." {
|
||||
continue
|
||||
}
|
||||
|
||||
// Clear entryDest before use it, some fields can be corrupted if does not set all fields in rawFS.Lookup
|
||||
*entryDest = fuse.EntryOut{}
|
||||
|
||||
d.rawFS.Lookup(&input.InHeader, e.Name, entryDest)
|
||||
d.lastOffset = off
|
||||
}
|
||||
return fuse.OK
|
||||
|
||||
}
|
||||
|
||||
type rawDir interface {
|
||||
ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
|
||||
ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
|
||||
}
|
||||
261
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files.go
generated
vendored
Normal file
261
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files.go
generated
vendored
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// DataFile is for implementing read-only filesystems. This
|
||||
// assumes we already have the data in memory.
|
||||
type dataFile struct {
|
||||
data []byte
|
||||
|
||||
File
|
||||
}
|
||||
|
||||
func (f *dataFile) String() string {
|
||||
l := len(f.data)
|
||||
if l > 10 {
|
||||
l = 10
|
||||
}
|
||||
|
||||
return fmt.Sprintf("dataFile(%x)", f.data[:l])
|
||||
}
|
||||
|
||||
func (f *dataFile) GetAttr(out *fuse.Attr) fuse.Status {
|
||||
out.Mode = fuse.S_IFREG | 0644
|
||||
out.Size = uint64(len(f.data))
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func NewDataFile(data []byte) File {
|
||||
f := new(dataFile)
|
||||
f.data = data
|
||||
f.File = NewDefaultFile()
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *dataFile) Read(buf []byte, off int64) (res fuse.ReadResult, code fuse.Status) {
|
||||
end := int(off) + int(len(buf))
|
||||
if end > len(f.data) {
|
||||
end = len(f.data)
|
||||
}
|
||||
|
||||
return fuse.ReadResultData(f.data[off:end]), fuse.OK
|
||||
}
|
||||
|
||||
type devNullFile struct {
|
||||
File
|
||||
}
|
||||
|
||||
// NewDevNullFile returns a file that accepts any write, and always
|
||||
// returns EOF for reads.
|
||||
func NewDevNullFile() File {
|
||||
return &devNullFile{
|
||||
File: NewDefaultFile(),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *devNullFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *devNullFile) String() string {
|
||||
return "devNullFile"
|
||||
}
|
||||
|
||||
func (f *devNullFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
|
||||
return fuse.ReadResultData(nil), fuse.OK
|
||||
}
|
||||
|
||||
func (f *devNullFile) Write(content []byte, off int64) (uint32, fuse.Status) {
|
||||
return uint32(len(content)), fuse.OK
|
||||
}
|
||||
|
||||
func (f *devNullFile) Flush() fuse.Status {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *devNullFile) Fsync(flags int) (code fuse.Status) {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *devNullFile) Truncate(size uint64) (code fuse.Status) {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
////////////////
|
||||
|
||||
// LoopbackFile delegates all operations back to an underlying os.File.
|
||||
func NewLoopbackFile(f *os.File) File {
|
||||
return &loopbackFile{File: f}
|
||||
}
|
||||
|
||||
type loopbackFile struct {
|
||||
File *os.File
|
||||
|
||||
// os.File is not threadsafe. Although fd themselves are
|
||||
// constant during the lifetime of an open file, the OS may
|
||||
// reuse the fd number after it is closed. When open races
|
||||
// with another close, they may lead to confusion as which
|
||||
// file gets written in the end.
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
func (f *loopbackFile) InnerFile() File {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *loopbackFile) SetInode(n *Inode) {
|
||||
}
|
||||
|
||||
func (f *loopbackFile) String() string {
|
||||
return fmt.Sprintf("loopbackFile(%s)", f.File.Name())
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Read(buf []byte, off int64) (res fuse.ReadResult, code fuse.Status) {
|
||||
f.lock.Lock()
|
||||
// This is not racy by virtue of the kernel properly
|
||||
// synchronizing the open/write/close.
|
||||
r := fuse.ReadResultFd(f.File.Fd(), off, len(buf))
|
||||
f.lock.Unlock()
|
||||
return r, fuse.OK
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
f.lock.Lock()
|
||||
n, err := f.File.WriteAt(data, off)
|
||||
f.lock.Unlock()
|
||||
return uint32(n), fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Release() {
|
||||
f.lock.Lock()
|
||||
f.File.Close()
|
||||
f.lock.Unlock()
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Flush() fuse.Status {
|
||||
f.lock.Lock()
|
||||
|
||||
// Since Flush() may be called for each dup'd fd, we don't
|
||||
// want to really close the file, we just want to flush. This
|
||||
// is achieved by closing a dup'd fd.
|
||||
newFd, err := syscall.Dup(int(f.File.Fd()))
|
||||
f.lock.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
err = syscall.Close(newFd)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Fsync(flags int) (code fuse.Status) {
|
||||
f.lock.Lock()
|
||||
r := fuse.ToStatus(syscall.Fsync(int(f.File.Fd())))
|
||||
f.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Flock(flags int) fuse.Status {
|
||||
f.lock.Lock()
|
||||
r := fuse.ToStatus(syscall.Flock(int(f.File.Fd()), flags))
|
||||
f.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Truncate(size uint64) fuse.Status {
|
||||
f.lock.Lock()
|
||||
r := fuse.ToStatus(syscall.Ftruncate(int(f.File.Fd()), int64(size)))
|
||||
f.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Chmod(mode uint32) fuse.Status {
|
||||
f.lock.Lock()
|
||||
r := fuse.ToStatus(f.File.Chmod(os.FileMode(mode)))
|
||||
f.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *loopbackFile) Chown(uid uint32, gid uint32) fuse.Status {
|
||||
f.lock.Lock()
|
||||
r := fuse.ToStatus(f.File.Chown(int(uid), int(gid)))
|
||||
f.lock.Unlock()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (f *loopbackFile) GetAttr(a *fuse.Attr) fuse.Status {
|
||||
st := syscall.Stat_t{}
|
||||
f.lock.Lock()
|
||||
err := syscall.Fstat(int(f.File.Fd()), &st)
|
||||
f.lock.Unlock()
|
||||
if err != nil {
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
a.FromStat(&st)
|
||||
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
// Utimens implemented in files_linux.go
|
||||
|
||||
// Allocate implemented in files_linux.go
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// NewReadOnlyFile wraps a File so all read/write operations are
|
||||
// denied.
|
||||
func NewReadOnlyFile(f File) File {
|
||||
return &readOnlyFile{File: f}
|
||||
}
|
||||
|
||||
type readOnlyFile struct {
|
||||
File
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) InnerFile() File {
|
||||
return f.File
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) String() string {
|
||||
return fmt.Sprintf("readOnlyFile(%s)", f.File.String())
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
return 0, fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Fsync(flag int) (code fuse.Status) {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Truncate(size uint64) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Chmod(mode uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Chown(uid uint32, gid uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *readOnlyFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
102
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files_darwin.go
generated
vendored
Normal file
102
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
|
||||
// TODO: Handle `mode` parameter.
|
||||
|
||||
// From `man fcntl` on OSX:
|
||||
// The F_PREALLOCATE command operates on the following structure:
|
||||
//
|
||||
// typedef struct fstore {
|
||||
// u_int32_t fst_flags; /* IN: flags word */
|
||||
// int fst_posmode; /* IN: indicates offset field */
|
||||
// off_t fst_offset; /* IN: start of the region */
|
||||
// off_t fst_length; /* IN: size of the region */
|
||||
// off_t fst_bytesalloc; /* OUT: number of bytes allocated */
|
||||
// } fstore_t;
|
||||
//
|
||||
// The flags (fst_flags) for the F_PREALLOCATE command are as follows:
|
||||
//
|
||||
// F_ALLOCATECONTIG Allocate contiguous space.
|
||||
//
|
||||
// F_ALLOCATEALL Allocate all requested space or no space at all.
|
||||
//
|
||||
// The position modes (fst_posmode) for the F_PREALLOCATE command indicate how to use the offset field. The modes are as fol-
|
||||
// lows:
|
||||
//
|
||||
// F_PEOFPOSMODE Allocate from the physical end of file.
|
||||
//
|
||||
// F_VOLPOSMODE Allocate from the volume offset.
|
||||
|
||||
k := struct {
|
||||
Flags uint32 // u_int32_t
|
||||
Posmode int64 // int
|
||||
Offset int64 // off_t
|
||||
Length int64 // off_t
|
||||
Bytesalloc int64 // off_t
|
||||
}{
|
||||
0,
|
||||
0,
|
||||
int64(off),
|
||||
int64(sz),
|
||||
0,
|
||||
}
|
||||
|
||||
// Linux version for reference:
|
||||
// err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
|
||||
|
||||
f.lock.Lock()
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_FCNTL, f.File.Fd(), uintptr(syscall.F_PREALLOCATE), uintptr(unsafe.Pointer(&k)))
|
||||
f.lock.Unlock()
|
||||
if errno != 0 {
|
||||
return fuse.ToStatus(errno)
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
const _UTIME_OMIT = ((1 << 30) - 2)
|
||||
|
||||
// timeToTimeval - Convert time.Time to syscall.Timeval
|
||||
//
|
||||
// Note: This does not use syscall.NsecToTimespec because
|
||||
// that does not work properly for times before 1970,
|
||||
// see https://github.com/golang/go/issues/12777
|
||||
func timeToTimeval(t *time.Time) syscall.Timeval {
|
||||
var tv syscall.Timeval
|
||||
tv.Usec = int32(t.Nanosecond() / 1000)
|
||||
tv.Sec = t.Unix()
|
||||
return tv
|
||||
}
|
||||
|
||||
// OSX does not have the utimensat syscall neded to implement this properly.
|
||||
// We do our best to emulate it using futimes.
|
||||
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
|
||||
tv := make([]syscall.Timeval, 2)
|
||||
if a == nil {
|
||||
tv[0].Usec = _UTIME_OMIT
|
||||
} else {
|
||||
tv[0] = timeToTimeval(a)
|
||||
}
|
||||
|
||||
if m == nil {
|
||||
tv[1].Usec = _UTIME_OMIT
|
||||
} else {
|
||||
tv[1] = timeToTimeval(m)
|
||||
}
|
||||
|
||||
f.lock.Lock()
|
||||
err := syscall.Futimes(int(f.File.Fd()), tv)
|
||||
f.lock.Unlock()
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
33
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files_linux.go
generated
vendored
Normal file
33
vendor/github.com/hanwen/go-fuse/fuse/nodefs/files_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
func (f *loopbackFile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
|
||||
f.lock.Lock()
|
||||
err := syscall.Fallocate(int(f.File.Fd()), mode, int64(off), int64(sz))
|
||||
f.lock.Unlock()
|
||||
if err != nil {
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
// Utimens - file handle based version of loopbackFileSystem.Utimens()
|
||||
func (f *loopbackFile) Utimens(a *time.Time, m *time.Time) fuse.Status {
|
||||
var ts [2]syscall.Timespec
|
||||
ts[0] = fuse.UtimeToTimespec(a)
|
||||
ts[1] = fuse.UtimeToTimespec(m)
|
||||
f.lock.Lock()
|
||||
err := futimens(int(f.File.Fd()), &ts)
|
||||
f.lock.Unlock()
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
424
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsconnector.go
generated
vendored
Normal file
424
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsconnector.go
generated
vendored
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
// This file contains the internal logic of the
|
||||
// FileSystemConnector. The functions for satisfying the raw interface
|
||||
// are in fsops.go
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// Tests should set to true.
|
||||
var paranoia = false
|
||||
|
||||
// FilesystemConnector translates the raw FUSE protocol (serialized
|
||||
// structs of uint32/uint64) to operations on Go objects representing
|
||||
// files and directories.
|
||||
type FileSystemConnector struct {
|
||||
debug bool
|
||||
|
||||
// Callbacks for talking back to the kernel.
|
||||
server *fuse.Server
|
||||
|
||||
// Translate between uint64 handles and *Inode.
|
||||
inodeMap handleMap
|
||||
|
||||
// The root of the FUSE file system.
|
||||
rootNode *Inode
|
||||
}
|
||||
|
||||
// NewOptions generates FUSE options that correspond to libfuse's
|
||||
// defaults.
|
||||
func NewOptions() *Options {
|
||||
return &Options{
|
||||
NegativeTimeout: 0,
|
||||
AttrTimeout: time.Second,
|
||||
EntryTimeout: time.Second,
|
||||
Owner: fuse.CurrentOwner(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewFileSystemConnector creates a FileSystemConnector with the given
|
||||
// options.
|
||||
func NewFileSystemConnector(root Node, opts *Options) (c *FileSystemConnector) {
|
||||
c = new(FileSystemConnector)
|
||||
if opts == nil {
|
||||
opts = NewOptions()
|
||||
}
|
||||
c.inodeMap = newPortableHandleMap()
|
||||
c.rootNode = newInode(true, root)
|
||||
|
||||
c.verify()
|
||||
c.mountRoot(opts)
|
||||
|
||||
// FUSE does not issue a LOOKUP for 1 (obviously), but it does
|
||||
// issue a forget. This lookupUpdate is to make the counts match.
|
||||
c.lookupUpdate(c.rootNode)
|
||||
c.debug = opts.Debug
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Server returns the fuse.Server that talking to the kernel.
|
||||
func (c *FileSystemConnector) Server() *fuse.Server {
|
||||
return c.server
|
||||
}
|
||||
|
||||
// SetDebug toggles printing of debug information. This function is
|
||||
// deprecated. Set the Debug option in the Options struct instead.
|
||||
func (c *FileSystemConnector) SetDebug(debug bool) {
|
||||
c.debug = debug
|
||||
}
|
||||
|
||||
// This verifies invariants of the data structure. This routine
|
||||
// acquires tree locks as it walks the inode tree.
|
||||
func (c *FileSystemConnector) verify() {
|
||||
if !paranoia {
|
||||
return
|
||||
}
|
||||
root := c.rootNode
|
||||
root.verify(c.rootNode.mountPoint)
|
||||
}
|
||||
|
||||
// childLookup fills entry information for a newly created child inode
|
||||
func (c *rawBridge) childLookup(out *fuse.EntryOut, n *Inode, context *fuse.Context) {
|
||||
n.Node().GetAttr((*fuse.Attr)(&out.Attr), nil, context)
|
||||
n.mount.fillEntry(out)
|
||||
out.NodeId, out.Generation = c.fsConn().lookupUpdate(n)
|
||||
if out.Ino == 0 {
|
||||
out.Ino = out.NodeId
|
||||
}
|
||||
if out.Nlink == 0 {
|
||||
// With Nlink == 0, newer kernels will refuse link
|
||||
// operations.
|
||||
out.Nlink = 1
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rawBridge) toInode(nodeid uint64) *Inode {
|
||||
if nodeid == fuse.FUSE_ROOT_ID {
|
||||
return c.rootNode
|
||||
}
|
||||
i := (*Inode)(unsafe.Pointer(c.inodeMap.Decode(nodeid)))
|
||||
return i
|
||||
}
|
||||
|
||||
// Must run outside treeLock. Returns the nodeId and generation.
|
||||
func (c *FileSystemConnector) lookupUpdate(node *Inode) (id, generation uint64) {
|
||||
id, generation = c.inodeMap.Register(&node.handled)
|
||||
c.verify()
|
||||
return
|
||||
}
|
||||
|
||||
// forgetUpdate decrements the reference counter for "nodeID" by "forgetCount".
|
||||
// Must run outside treeLock.
|
||||
func (c *FileSystemConnector) forgetUpdate(nodeID uint64, forgetCount int) {
|
||||
if nodeID == fuse.FUSE_ROOT_ID {
|
||||
c.rootNode.Node().OnUnmount()
|
||||
|
||||
// We never got a lookup for root, so don't try to
|
||||
// forget root.
|
||||
return
|
||||
}
|
||||
|
||||
// Prevent concurrent modification of the tree while we are processing
|
||||
// the FORGET
|
||||
node := (*Inode)(unsafe.Pointer(c.inodeMap.Decode(nodeID)))
|
||||
node.mount.treeLock.Lock()
|
||||
defer node.mount.treeLock.Unlock()
|
||||
|
||||
if forgotten, _ := c.inodeMap.Forget(nodeID, forgetCount); forgotten {
|
||||
if len(node.children) > 0 || !node.Node().Deletable() ||
|
||||
node == c.rootNode || node.mountPoint != nil {
|
||||
// We cannot forget a directory that still has children as these
|
||||
// would become unreachable.
|
||||
return
|
||||
}
|
||||
// We have to remove ourself from all parents.
|
||||
// Create a copy of node.parents so we can safely iterate over it
|
||||
// while modifying the original.
|
||||
parents := make(map[parentData]struct{}, len(node.parents))
|
||||
for k, v := range node.parents {
|
||||
parents[k] = v
|
||||
}
|
||||
|
||||
for p := range parents {
|
||||
// This also modifies node.parents
|
||||
p.parent.rmChild(p.name)
|
||||
}
|
||||
|
||||
node.fsInode.OnForget()
|
||||
}
|
||||
// TODO - try to drop children even forget was not successful.
|
||||
c.verify()
|
||||
}
|
||||
|
||||
// InodeCount returns the number of inodes registered with the kernel.
|
||||
func (c *FileSystemConnector) InodeHandleCount() int {
|
||||
return c.inodeMap.Count()
|
||||
}
|
||||
|
||||
// Finds a node within the currently known inodes, returns the last
|
||||
// known node and the remaining unknown path components. If parent is
|
||||
// nil, start from FUSE mountpoint.
|
||||
func (c *FileSystemConnector) Node(parent *Inode, fullPath string) (*Inode, []string) {
|
||||
if parent == nil {
|
||||
parent = c.rootNode
|
||||
}
|
||||
if fullPath == "" {
|
||||
return parent, nil
|
||||
}
|
||||
|
||||
sep := string(filepath.Separator)
|
||||
fullPath = strings.TrimLeft(filepath.Clean(fullPath), sep)
|
||||
comps := strings.Split(fullPath, sep)
|
||||
|
||||
node := parent
|
||||
if node.mountPoint == nil {
|
||||
node.mount.treeLock.RLock()
|
||||
defer node.mount.treeLock.RUnlock()
|
||||
}
|
||||
|
||||
for i, component := range comps {
|
||||
if len(component) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if node.mountPoint != nil {
|
||||
node.mount.treeLock.RLock()
|
||||
defer node.mount.treeLock.RUnlock()
|
||||
}
|
||||
|
||||
next := node.children[component]
|
||||
if next == nil {
|
||||
return node, comps[i:]
|
||||
}
|
||||
node = next
|
||||
}
|
||||
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// Follows the path from the given parent, doing lookups as
|
||||
// necessary. The path should be '/' separated without leading slash.
|
||||
func (c *FileSystemConnector) LookupNode(parent *Inode, path string) *Inode {
|
||||
if path == "" {
|
||||
return parent
|
||||
}
|
||||
|
||||
components := strings.Split(path, "/")
|
||||
for _, r := range components {
|
||||
var a fuse.Attr
|
||||
// This will not affect inode ID lookup counts, which
|
||||
// are only update in response to kernel requests.
|
||||
var dummy fuse.InHeader
|
||||
child, _ := c.internalLookup(&a, parent, r, &dummy)
|
||||
if child == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
parent = child
|
||||
}
|
||||
|
||||
return parent
|
||||
}
|
||||
|
||||
func (c *FileSystemConnector) mountRoot(opts *Options) {
|
||||
c.rootNode.mountFs(opts)
|
||||
c.rootNode.mount.connector = c
|
||||
c.verify()
|
||||
}
|
||||
|
||||
// Mount() generates a synthetic directory node, and mounts the file
|
||||
// system there. If opts is nil, the mount options of the root file
|
||||
// system are inherited. The encompassing filesystem should pretend
|
||||
// the mount point does not exist.
|
||||
//
|
||||
// It returns ENOENT if the directory containing the mount point does
|
||||
// not exist, and EBUSY if the intended mount point already exists.
|
||||
func (c *FileSystemConnector) Mount(parent *Inode, name string, root Node, opts *Options) fuse.Status {
|
||||
node, code := c.lockMount(parent, name, root, opts)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
node.Node().OnMount(c)
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *FileSystemConnector) lockMount(parent *Inode, name string, root Node, opts *Options) (*Inode, fuse.Status) {
|
||||
defer c.verify()
|
||||
parent.mount.treeLock.Lock()
|
||||
defer parent.mount.treeLock.Unlock()
|
||||
node := parent.children[name]
|
||||
if node != nil {
|
||||
return nil, fuse.EBUSY
|
||||
}
|
||||
|
||||
node = newInode(true, root)
|
||||
if opts == nil {
|
||||
opts = c.rootNode.mountPoint.options
|
||||
}
|
||||
|
||||
node.mountFs(opts)
|
||||
node.mount.connector = c
|
||||
parent.addChild(name, node)
|
||||
|
||||
node.mountPoint.parentInode = parent
|
||||
if c.debug {
|
||||
log.Printf("Mount %T on subdir %s, parent %d", node,
|
||||
name, c.inodeMap.Handle(&parent.handled))
|
||||
}
|
||||
return node, fuse.OK
|
||||
}
|
||||
|
||||
// Unmount() tries to unmount the given inode. It returns EINVAL if the
|
||||
// path does not exist, or is not a mount point, and EBUSY if there
|
||||
// are open files or submounts below this node.
|
||||
func (c *FileSystemConnector) Unmount(node *Inode) fuse.Status {
|
||||
// TODO - racy.
|
||||
if node.mountPoint == nil {
|
||||
log.Println("not a mountpoint:", c.inodeMap.Handle(&node.handled))
|
||||
return fuse.EINVAL
|
||||
}
|
||||
|
||||
nodeID := c.inodeMap.Handle(&node.handled)
|
||||
|
||||
// Must lock parent to update tree structure.
|
||||
parentNode := node.mountPoint.parentInode
|
||||
parentNode.mount.treeLock.Lock()
|
||||
defer parentNode.mount.treeLock.Unlock()
|
||||
|
||||
mount := node.mountPoint
|
||||
name := node.mountPoint.mountName()
|
||||
if mount.openFiles.Count() > 0 {
|
||||
return fuse.EBUSY
|
||||
}
|
||||
|
||||
node.mount.treeLock.Lock()
|
||||
defer node.mount.treeLock.Unlock()
|
||||
|
||||
if mount.mountInode != node {
|
||||
log.Panicf("got two different mount inodes %v vs %v",
|
||||
c.inodeMap.Handle(&mount.mountInode.handled),
|
||||
c.inodeMap.Handle(&node.handled))
|
||||
}
|
||||
|
||||
if !node.canUnmount() {
|
||||
return fuse.EBUSY
|
||||
}
|
||||
|
||||
delete(parentNode.children, name)
|
||||
node.Node().OnUnmount()
|
||||
|
||||
parentId := c.inodeMap.Handle(&parentNode.handled)
|
||||
if parentNode == c.rootNode {
|
||||
// TODO - test coverage. Currently covered by zipfs/multizip_test.go
|
||||
parentId = fuse.FUSE_ROOT_ID
|
||||
}
|
||||
|
||||
// We have to wait until the kernel has forgotten the
|
||||
// mountpoint, so the write to node.mountPoint is no longer
|
||||
// racy.
|
||||
mount.treeLock.Unlock()
|
||||
parentNode.mount.treeLock.Unlock()
|
||||
code := c.server.DeleteNotify(parentId, nodeID, name)
|
||||
|
||||
if code.Ok() {
|
||||
delay := 100 * time.Microsecond
|
||||
|
||||
for {
|
||||
// This operation is rare, so we kludge it to avoid
|
||||
// contention.
|
||||
time.Sleep(delay)
|
||||
delay = delay * 2
|
||||
if !c.inodeMap.Has(nodeID) {
|
||||
break
|
||||
}
|
||||
|
||||
if delay >= time.Second {
|
||||
// We limit the wait at one second. If
|
||||
// it takes longer, something else is
|
||||
// amiss, and we would be waiting forever.
|
||||
log.Println("kernel did not issue FORGET for node on Unmount.")
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parentNode.mount.treeLock.Lock()
|
||||
mount.treeLock.Lock()
|
||||
mount.mountInode = nil
|
||||
node.mountPoint = nil
|
||||
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
// FileNotify notifies the kernel that data and metadata of this inode
|
||||
// has changed. After this call completes, the kernel will issue a
|
||||
// new GetAttr requests for metadata and new Read calls for content.
|
||||
// Use negative offset for metadata-only invalidation, and zero-length
|
||||
// for invalidating all content.
|
||||
func (c *FileSystemConnector) FileNotify(node *Inode, off int64, length int64) fuse.Status {
|
||||
var nId uint64
|
||||
if node == c.rootNode {
|
||||
nId = fuse.FUSE_ROOT_ID
|
||||
} else {
|
||||
nId = c.inodeMap.Handle(&node.handled)
|
||||
}
|
||||
|
||||
if nId == 0 {
|
||||
return fuse.OK
|
||||
}
|
||||
return c.server.InodeNotify(nId, off, length)
|
||||
}
|
||||
|
||||
// EntryNotify makes the kernel forget the entry data from the given
|
||||
// name from a directory. After this call, the kernel will issue a
|
||||
// new lookup request for the given name when necessary. No filesystem
|
||||
// related locks should be held when calling this.
|
||||
func (c *FileSystemConnector) EntryNotify(node *Inode, name string) fuse.Status {
|
||||
var nId uint64
|
||||
if node == c.rootNode {
|
||||
nId = fuse.FUSE_ROOT_ID
|
||||
} else {
|
||||
nId = c.inodeMap.Handle(&node.handled)
|
||||
}
|
||||
|
||||
if nId == 0 {
|
||||
return fuse.OK
|
||||
}
|
||||
return c.server.EntryNotify(nId, name)
|
||||
}
|
||||
|
||||
// DeleteNotify signals to the kernel that the named entry in dir for
|
||||
// the child disappeared. No filesystem related locks should be held
|
||||
// when calling this.
|
||||
func (c *FileSystemConnector) DeleteNotify(dir *Inode, child *Inode, name string) fuse.Status {
|
||||
var nId uint64
|
||||
|
||||
if dir == c.rootNode {
|
||||
nId = fuse.FUSE_ROOT_ID
|
||||
} else {
|
||||
nId = c.inodeMap.Handle(&dir.handled)
|
||||
}
|
||||
|
||||
if nId == 0 {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
chId := c.inodeMap.Handle(&child.handled)
|
||||
|
||||
return c.server.DeleteNotify(nId, chId, name)
|
||||
}
|
||||
158
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsmount.go
generated
vendored
Normal file
158
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsmount.go
generated
vendored
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// openedFile stores either an open dir or an open file.
|
||||
type openedFile struct {
|
||||
handled
|
||||
|
||||
WithFlags
|
||||
|
||||
dir *connectorDir
|
||||
}
|
||||
|
||||
type fileSystemMount struct {
|
||||
// Node that we were mounted on.
|
||||
mountInode *Inode
|
||||
|
||||
// Parent to the mountInode.
|
||||
parentInode *Inode
|
||||
|
||||
// Options for the mount.
|
||||
options *Options
|
||||
|
||||
// Protects the "children" and "parents" hashmaps of the inodes
|
||||
// within the mount.
|
||||
// treeLock should be acquired before openFilesLock.
|
||||
//
|
||||
// If multiple treeLocks must be acquired, the treeLocks
|
||||
// closer to the root must be acquired first.
|
||||
treeLock sync.RWMutex
|
||||
|
||||
// Manage filehandles of open files.
|
||||
openFiles handleMap
|
||||
|
||||
Debug bool
|
||||
|
||||
connector *FileSystemConnector
|
||||
}
|
||||
|
||||
// Must called with lock for parent held.
|
||||
func (m *fileSystemMount) mountName() string {
|
||||
for k, v := range m.parentInode.children {
|
||||
if m.mountInode == v {
|
||||
return k
|
||||
}
|
||||
}
|
||||
panic("not found")
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) setOwner(attr *fuse.Attr) {
|
||||
if m.options.Owner != nil {
|
||||
attr.Owner = *(*fuse.Owner)(m.options.Owner)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) fillEntry(out *fuse.EntryOut) {
|
||||
splitDuration(m.options.EntryTimeout, &out.EntryValid, &out.EntryValidNsec)
|
||||
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
|
||||
m.setOwner(&out.Attr)
|
||||
if out.Mode&fuse.S_IFDIR == 0 && out.Nlink == 0 {
|
||||
out.Nlink = 1
|
||||
}
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) fillAttr(out *fuse.AttrOut, nodeId uint64) {
|
||||
splitDuration(m.options.AttrTimeout, &out.AttrValid, &out.AttrValidNsec)
|
||||
m.setOwner(&out.Attr)
|
||||
if out.Ino == 0 {
|
||||
out.Ino = nodeId
|
||||
}
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) getOpenedFile(h uint64) *openedFile {
|
||||
var b *openedFile
|
||||
if h != 0 {
|
||||
b = (*openedFile)(unsafe.Pointer(m.openFiles.Decode(h)))
|
||||
}
|
||||
|
||||
if b != nil && m.connector.debug && b.WithFlags.Description != "" {
|
||||
log.Printf("File %d = %q", h, b.WithFlags.Description)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) unregisterFileHandle(handle uint64, node *Inode) *openedFile {
|
||||
_, obj := m.openFiles.Forget(handle, 1)
|
||||
opened := (*openedFile)(unsafe.Pointer(obj))
|
||||
node.openFilesMutex.Lock()
|
||||
idx := -1
|
||||
for i, v := range node.openFiles {
|
||||
if v == opened {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
l := len(node.openFiles)
|
||||
if idx == l-1 {
|
||||
node.openFiles[idx] = nil
|
||||
} else {
|
||||
node.openFiles[idx] = node.openFiles[l-1]
|
||||
}
|
||||
node.openFiles = node.openFiles[:l-1]
|
||||
node.openFilesMutex.Unlock()
|
||||
|
||||
return opened
|
||||
}
|
||||
|
||||
func (m *fileSystemMount) registerFileHandle(node *Inode, dir *connectorDir, f File, flags uint32) (uint64, *openedFile) {
|
||||
node.openFilesMutex.Lock()
|
||||
b := &openedFile{
|
||||
dir: dir,
|
||||
WithFlags: WithFlags{
|
||||
File: f,
|
||||
OpenFlags: flags,
|
||||
},
|
||||
}
|
||||
|
||||
for {
|
||||
withFlags, ok := f.(*WithFlags)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
b.WithFlags.File = withFlags.File
|
||||
b.WithFlags.FuseFlags |= withFlags.FuseFlags
|
||||
b.WithFlags.Description += withFlags.Description
|
||||
f = withFlags.File
|
||||
}
|
||||
|
||||
if b.WithFlags.File != nil {
|
||||
b.WithFlags.File.SetInode(node)
|
||||
}
|
||||
node.openFiles = append(node.openFiles, b)
|
||||
handle, _ := m.openFiles.Register(&b.handled)
|
||||
node.openFilesMutex.Unlock()
|
||||
return handle, b
|
||||
}
|
||||
|
||||
// Creates a return entry for a non-existent path.
|
||||
func (m *fileSystemMount) negativeEntry(out *fuse.EntryOut) bool {
|
||||
if m.options.NegativeTimeout > 0.0 {
|
||||
out.NodeId = 0
|
||||
splitDuration(m.options.NegativeTimeout, &out.EntryValid, &out.EntryValidNsec)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
487
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsops.go
generated
vendored
Normal file
487
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fsops.go
generated
vendored
Normal file
|
|
@ -0,0 +1,487 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
// This file contains FileSystemConnector's implementation of
|
||||
// RawFileSystem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// Returns the RawFileSystem so it can be mounted.
|
||||
func (c *FileSystemConnector) RawFS() fuse.RawFileSystem {
|
||||
return (*rawBridge)(c)
|
||||
}
|
||||
|
||||
type rawBridge FileSystemConnector
|
||||
|
||||
func (c *rawBridge) Fsync(input *fuse.FsyncIn) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
|
||||
if opened != nil {
|
||||
return opened.WithFlags.File.Fsync(int(input.FsyncFlags))
|
||||
}
|
||||
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (c *rawBridge) SetDebug(debug bool) {
|
||||
c.fsConn().SetDebug(debug)
|
||||
}
|
||||
|
||||
func (c *rawBridge) FsyncDir(input *fuse.FsyncIn) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (c *rawBridge) fsConn() *FileSystemConnector {
|
||||
return (*FileSystemConnector)(c)
|
||||
}
|
||||
|
||||
func (c *rawBridge) String() string {
|
||||
if c.rootNode == nil || c.rootNode.mount == nil {
|
||||
return "go-fuse:unmounted"
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%T", c.rootNode.Node())
|
||||
name = strings.TrimLeft(name, "*")
|
||||
return name
|
||||
}
|
||||
|
||||
func (c *rawBridge) Init(s *fuse.Server) {
|
||||
c.server = s
|
||||
c.rootNode.Node().OnMount((*FileSystemConnector)(c))
|
||||
}
|
||||
|
||||
func (c *FileSystemConnector) lookupMountUpdate(out *fuse.Attr, mount *fileSystemMount) (node *Inode, code fuse.Status) {
|
||||
code = mount.mountInode.Node().GetAttr(out, nil, nil)
|
||||
if !code.Ok() {
|
||||
log.Println("Root getattr should not return error", code)
|
||||
out.Mode = fuse.S_IFDIR | 0755
|
||||
return mount.mountInode, fuse.OK
|
||||
}
|
||||
|
||||
return mount.mountInode, fuse.OK
|
||||
}
|
||||
|
||||
// internalLookup executes a lookup without affecting NodeId reference counts.
|
||||
func (c *FileSystemConnector) internalLookup(out *fuse.Attr, parent *Inode, name string, header *fuse.InHeader) (node *Inode, code fuse.Status) {
|
||||
|
||||
// We may already know the child because it was created using Create or Mkdir,
|
||||
// from an earlier lookup, or because the nodes were created in advance
|
||||
// (in-memory filesystems).
|
||||
child := parent.GetChild(name)
|
||||
|
||||
if child != nil && child.mountPoint != nil {
|
||||
return c.lookupMountUpdate(out, child.mountPoint)
|
||||
}
|
||||
|
||||
if child != nil {
|
||||
parent = nil
|
||||
}
|
||||
if child != nil {
|
||||
code = child.fsInode.GetAttr(out, nil, &header.Context)
|
||||
} else {
|
||||
child, code = parent.fsInode.Lookup(out, name, &header.Context)
|
||||
}
|
||||
|
||||
return child, code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Lookup(header *fuse.InHeader, name string, out *fuse.EntryOut) (code fuse.Status) {
|
||||
parent := c.toInode(header.NodeId)
|
||||
if !parent.IsDir() {
|
||||
log.Printf("Lookup %q called on non-Directory node %d", name, header.NodeId)
|
||||
return fuse.ENOTDIR
|
||||
}
|
||||
outAttr := (*fuse.Attr)(&out.Attr)
|
||||
child, code := c.fsConn().internalLookup(outAttr, parent, name, header)
|
||||
if code == fuse.ENOENT && parent.mount.negativeEntry(out) {
|
||||
return fuse.OK
|
||||
}
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
if child == nil {
|
||||
log.Println("Lookup returned fuse.OK with nil child", name)
|
||||
}
|
||||
|
||||
child.mount.fillEntry(out)
|
||||
out.NodeId, out.Generation = c.fsConn().lookupUpdate(child)
|
||||
if out.Ino == 0 {
|
||||
out.Ino = out.NodeId
|
||||
}
|
||||
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (c *rawBridge) Forget(nodeID, nlookup uint64) {
|
||||
c.fsConn().forgetUpdate(nodeID, int(nlookup))
|
||||
}
|
||||
|
||||
func (c *rawBridge) GetAttr(input *fuse.GetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
|
||||
var f File
|
||||
if input.Flags()&fuse.FUSE_GETATTR_FH != 0 {
|
||||
if opened := node.mount.getOpenedFile(input.Fh()); opened != nil {
|
||||
f = opened.WithFlags.File
|
||||
}
|
||||
}
|
||||
|
||||
dest := (*fuse.Attr)(&out.Attr)
|
||||
code = node.fsInode.GetAttr(dest, f, &input.Context)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
if out.Nlink == 0 {
|
||||
// With Nlink == 0, newer kernels will refuse link
|
||||
// operations.
|
||||
out.Nlink = 1
|
||||
}
|
||||
|
||||
node.mount.fillAttr(out, input.NodeId)
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (c *rawBridge) OpenDir(input *fuse.OpenIn, out *fuse.OpenOut) (code fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
stream, err := node.fsInode.OpenDir(&input.Context)
|
||||
if err != fuse.OK {
|
||||
return err
|
||||
}
|
||||
stream = append(stream, node.getMountDirEntries()...)
|
||||
de := &connectorDir{
|
||||
node: node.Node(),
|
||||
stream: append(stream,
|
||||
fuse.DirEntry{Mode: fuse.S_IFDIR, Name: "."},
|
||||
fuse.DirEntry{Mode: fuse.S_IFDIR, Name: ".."}),
|
||||
rawFS: c,
|
||||
}
|
||||
h, opened := node.mount.registerFileHandle(node, de, nil, input.Flags)
|
||||
out.OpenFlags = opened.FuseFlags
|
||||
out.Fh = h
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (c *rawBridge) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
return opened.dir.ReadDir(input, out)
|
||||
}
|
||||
|
||||
func (c *rawBridge) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
return opened.dir.ReadDirPlus(input, out)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Open(input *fuse.OpenIn, out *fuse.OpenOut) (status fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
f, code := node.fsInode.Open(input.Flags, &input.Context)
|
||||
if !code.Ok() || f == nil {
|
||||
return code
|
||||
}
|
||||
h, opened := node.mount.registerFileHandle(node, nil, f, input.Flags)
|
||||
out.OpenFlags = opened.FuseFlags
|
||||
out.Fh = h
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (c *rawBridge) SetAttr(input *fuse.SetAttrIn, out *fuse.AttrOut) (code fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
|
||||
var f File
|
||||
if input.Valid&fuse.FATTR_FH != 0 {
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
f = opened.WithFlags.File
|
||||
}
|
||||
|
||||
if code.Ok() && input.Valid&fuse.FATTR_MODE != 0 {
|
||||
permissions := uint32(07777) & input.Mode
|
||||
code = node.fsInode.Chmod(f, permissions, &input.Context)
|
||||
}
|
||||
if code.Ok() && (input.Valid&(fuse.FATTR_UID|fuse.FATTR_GID) != 0) {
|
||||
var uid uint32 = ^uint32(0) // means "do not change" in chown(2)
|
||||
var gid uint32 = ^uint32(0)
|
||||
if input.Valid&fuse.FATTR_UID != 0 {
|
||||
uid = input.Uid
|
||||
}
|
||||
if input.Valid&fuse.FATTR_GID != 0 {
|
||||
gid = input.Gid
|
||||
}
|
||||
code = node.fsInode.Chown(f, uid, gid, &input.Context)
|
||||
}
|
||||
if code.Ok() && input.Valid&fuse.FATTR_SIZE != 0 {
|
||||
code = node.fsInode.Truncate(f, input.Size, &input.Context)
|
||||
}
|
||||
if code.Ok() && (input.Valid&(fuse.FATTR_ATIME|fuse.FATTR_MTIME|fuse.FATTR_ATIME_NOW|fuse.FATTR_MTIME_NOW) != 0) {
|
||||
now := time.Now()
|
||||
var atime *time.Time
|
||||
var mtime *time.Time
|
||||
|
||||
if input.Valid&fuse.FATTR_ATIME != 0 {
|
||||
if input.Valid&fuse.FATTR_ATIME_NOW != 0 {
|
||||
atime = &now
|
||||
} else {
|
||||
t := time.Unix(int64(input.Atime), int64(input.Atimensec))
|
||||
atime = &t
|
||||
}
|
||||
}
|
||||
|
||||
if input.Valid&fuse.FATTR_MTIME != 0 {
|
||||
if input.Valid&fuse.FATTR_MTIME_NOW != 0 {
|
||||
mtime = &now
|
||||
} else {
|
||||
t := time.Unix(int64(input.Mtime), int64(input.Mtimensec))
|
||||
mtime = &t
|
||||
}
|
||||
}
|
||||
|
||||
code = node.fsInode.Utimens(f, atime, mtime, &input.Context)
|
||||
}
|
||||
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
// Must call GetAttr(); the filesystem may override some of
|
||||
// the changes we effect here.
|
||||
attr := (*fuse.Attr)(&out.Attr)
|
||||
code = node.fsInode.GetAttr(attr, nil, &input.Context)
|
||||
if code.Ok() {
|
||||
node.mount.fillAttr(out, input.NodeId)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Fallocate(input *fuse.FallocateIn) (code fuse.Status) {
|
||||
n := c.toInode(input.NodeId)
|
||||
opened := n.mount.getOpenedFile(input.Fh)
|
||||
|
||||
return n.fsInode.Fallocate(opened, input.Offset, input.Length, input.Mode, &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Readlink(header *fuse.InHeader) (out []byte, code fuse.Status) {
|
||||
n := c.toInode(header.NodeId)
|
||||
return n.fsInode.Readlink(&header.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Mknod(input *fuse.MknodIn, name string, out *fuse.EntryOut) (code fuse.Status) {
|
||||
parent := c.toInode(input.NodeId)
|
||||
|
||||
child, code := parent.fsInode.Mknod(name, input.Mode, uint32(input.Rdev), &input.Context)
|
||||
if code.Ok() {
|
||||
c.childLookup(out, child, &input.Context)
|
||||
code = child.fsInode.GetAttr((*fuse.Attr)(&out.Attr), nil, &input.Context)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Mkdir(input *fuse.MkdirIn, name string, out *fuse.EntryOut) (code fuse.Status) {
|
||||
parent := c.toInode(input.NodeId)
|
||||
|
||||
child, code := parent.fsInode.Mkdir(name, input.Mode, &input.Context)
|
||||
if code.Ok() {
|
||||
c.childLookup(out, child, &input.Context)
|
||||
code = child.fsInode.GetAttr((*fuse.Attr)(&out.Attr), nil, &input.Context)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Unlink(header *fuse.InHeader, name string) (code fuse.Status) {
|
||||
parent := c.toInode(header.NodeId)
|
||||
return parent.fsInode.Unlink(name, &header.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Rmdir(header *fuse.InHeader, name string) (code fuse.Status) {
|
||||
parent := c.toInode(header.NodeId)
|
||||
return parent.fsInode.Rmdir(name, &header.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Symlink(header *fuse.InHeader, pointedTo string, linkName string, out *fuse.EntryOut) (code fuse.Status) {
|
||||
parent := c.toInode(header.NodeId)
|
||||
|
||||
child, code := parent.fsInode.Symlink(linkName, pointedTo, &header.Context)
|
||||
if code.Ok() {
|
||||
c.childLookup(out, child, &header.Context)
|
||||
code = child.fsInode.GetAttr((*fuse.Attr)(&out.Attr), nil, &header.Context)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Rename(input *fuse.RenameIn, oldName string, newName string) (code fuse.Status) {
|
||||
oldParent := c.toInode(input.NodeId)
|
||||
|
||||
child := oldParent.GetChild(oldName)
|
||||
if child == nil {
|
||||
return fuse.ENOENT
|
||||
}
|
||||
if child.mountPoint != nil {
|
||||
return fuse.EBUSY
|
||||
}
|
||||
|
||||
newParent := c.toInode(input.Newdir)
|
||||
if oldParent.mount != newParent.mount {
|
||||
return fuse.EXDEV
|
||||
}
|
||||
|
||||
return oldParent.fsInode.Rename(oldName, newParent.fsInode, newName, &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Link(input *fuse.LinkIn, name string, out *fuse.EntryOut) (code fuse.Status) {
|
||||
existing := c.toInode(input.Oldnodeid)
|
||||
parent := c.toInode(input.NodeId)
|
||||
|
||||
if existing.mount != parent.mount {
|
||||
return fuse.EXDEV
|
||||
}
|
||||
|
||||
child, code := parent.fsInode.Link(name, existing.fsInode, &input.Context)
|
||||
if code.Ok() {
|
||||
c.childLookup(out, child, &input.Context)
|
||||
code = child.fsInode.GetAttr((*fuse.Attr)(&out.Attr), nil, &input.Context)
|
||||
}
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Access(input *fuse.AccessIn) (code fuse.Status) {
|
||||
n := c.toInode(input.NodeId)
|
||||
return n.fsInode.Access(input.Mask, &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Create(input *fuse.CreateIn, name string, out *fuse.CreateOut) (code fuse.Status) {
|
||||
parent := c.toInode(input.NodeId)
|
||||
f, child, code := parent.fsInode.Create(name, uint32(input.Flags), input.Mode, &input.Context)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
c.childLookup(&out.EntryOut, child, &input.Context)
|
||||
handle, opened := parent.mount.registerFileHandle(child, nil, f, input.Flags)
|
||||
|
||||
out.OpenOut.OpenFlags = opened.FuseFlags
|
||||
out.OpenOut.Fh = handle
|
||||
return code
|
||||
}
|
||||
|
||||
func (c *rawBridge) Release(input *fuse.ReleaseIn) {
|
||||
if input.Fh != 0 {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.unregisterFileHandle(input.Fh, node)
|
||||
opened.WithFlags.File.Release()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rawBridge) ReleaseDir(input *fuse.ReleaseIn) {
|
||||
if input.Fh != 0 {
|
||||
node := c.toInode(input.NodeId)
|
||||
node.mount.unregisterFileHandle(input.Fh, node)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *rawBridge) GetXAttrSize(header *fuse.InHeader, attribute string) (sz int, code fuse.Status) {
|
||||
node := c.toInode(header.NodeId)
|
||||
data, errno := node.fsInode.GetXAttr(attribute, &header.Context)
|
||||
return len(data), errno
|
||||
}
|
||||
|
||||
func (c *rawBridge) GetXAttrData(header *fuse.InHeader, attribute string) (data []byte, code fuse.Status) {
|
||||
node := c.toInode(header.NodeId)
|
||||
return node.fsInode.GetXAttr(attribute, &header.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) RemoveXAttr(header *fuse.InHeader, attr string) fuse.Status {
|
||||
node := c.toInode(header.NodeId)
|
||||
return node.fsInode.RemoveXAttr(attr, &header.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) SetXAttr(input *fuse.SetXAttrIn, attr string, data []byte) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
return node.fsInode.SetXAttr(attr, data, int(input.Flags), &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) ListXAttr(header *fuse.InHeader) (data []byte, code fuse.Status) {
|
||||
node := c.toInode(header.NodeId)
|
||||
attrs, code := node.fsInode.ListXAttr(&header.Context)
|
||||
if code != fuse.OK {
|
||||
return nil, code
|
||||
}
|
||||
|
||||
b := bytes.NewBuffer([]byte{})
|
||||
for _, v := range attrs {
|
||||
b.Write([]byte(v))
|
||||
b.WriteByte(0)
|
||||
}
|
||||
|
||||
return b.Bytes(), code
|
||||
}
|
||||
|
||||
////////////////
|
||||
// files.
|
||||
|
||||
func (c *rawBridge) Write(input *fuse.WriteIn, data []byte) (written uint32, code fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
|
||||
var f File
|
||||
if opened != nil {
|
||||
f = opened.WithFlags.File
|
||||
}
|
||||
|
||||
return node.Node().Write(f, data, int64(input.Offset), &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Read(input *fuse.ReadIn, buf []byte) (fuse.ReadResult, fuse.Status) {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
|
||||
var f File
|
||||
if opened != nil {
|
||||
f = opened.WithFlags.File
|
||||
}
|
||||
|
||||
return node.Node().Read(f, buf, int64(input.Offset), &input.Context)
|
||||
}
|
||||
|
||||
func (c *rawBridge) Flock(input *fuse.FlockIn, flags int) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
|
||||
if opened != nil {
|
||||
return opened.WithFlags.File.Flock(flags)
|
||||
}
|
||||
|
||||
return fuse.EBADF
|
||||
}
|
||||
|
||||
func (c *rawBridge) StatFs(header *fuse.InHeader, out *fuse.StatfsOut) fuse.Status {
|
||||
node := c.toInode(header.NodeId)
|
||||
s := node.Node().StatFs()
|
||||
if s == nil {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
*out = *s
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (c *rawBridge) Flush(input *fuse.FlushIn) fuse.Status {
|
||||
node := c.toInode(input.NodeId)
|
||||
opened := node.mount.getOpenedFile(input.Fh)
|
||||
|
||||
if opened != nil {
|
||||
return opened.WithFlags.File.Flush()
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
24
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fuse.go
generated
vendored
Normal file
24
vendor/github.com/hanwen/go-fuse/fuse/nodefs/fuse.go
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// Mounts a filesystem with the given root node on the given directory
|
||||
func MountRoot(mountpoint string, root Node, opts *Options) (*fuse.Server, *FileSystemConnector, error) {
|
||||
conn := NewFileSystemConnector(root, opts)
|
||||
|
||||
mountOpts := fuse.MountOptions{}
|
||||
if opts != nil && opts.Debug {
|
||||
mountOpts.Debug = opts.Debug
|
||||
}
|
||||
s, err := fuse.NewServer(conn.RawFS(), mountpoint, &mountOpts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return s, conn, nil
|
||||
}
|
||||
151
vendor/github.com/hanwen/go-fuse/fuse/nodefs/handle.go
generated
vendored
Normal file
151
vendor/github.com/hanwen/go-fuse/fuse/nodefs/handle.go
generated
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HandleMap translates objects in Go space to 64-bit handles that can
|
||||
// be given out to -say- the linux kernel as NodeIds.
|
||||
//
|
||||
// The 32 bits version of this is a threadsafe wrapper around a map.
|
||||
//
|
||||
// To use it, include "handled" as first member of the structure
|
||||
// you wish to export.
|
||||
//
|
||||
// This structure is thread-safe.
|
||||
type handleMap interface {
|
||||
// Register stores "obj" and returns a unique (NodeId, generation) tuple.
|
||||
Register(obj *handled) (handle, generation uint64)
|
||||
Count() int
|
||||
// Decode retrieves a stored object from its 64-bit handle.
|
||||
Decode(uint64) *handled
|
||||
// Forget decrements the reference counter for "handle" by "count" and drops
|
||||
// the object if the refcount reaches zero.
|
||||
// Returns a boolean whether the object was dropped and the object itself.
|
||||
Forget(handle uint64, count int) (bool, *handled)
|
||||
// Handle gets the object's NodeId.
|
||||
Handle(obj *handled) uint64
|
||||
// Has checks if NodeId is stored.
|
||||
Has(uint64) bool
|
||||
}
|
||||
|
||||
type handled struct {
|
||||
check uint32
|
||||
handle uint64
|
||||
count int
|
||||
}
|
||||
|
||||
func (h *handled) verify() {
|
||||
if h.count < 0 {
|
||||
log.Panicf("negative lookup count %d", h.count)
|
||||
}
|
||||
if (h.count == 0) != (h.handle == 0) {
|
||||
log.Panicf("registration mismatch: lookup %d id %d", h.count, h.handle)
|
||||
}
|
||||
}
|
||||
|
||||
const _ALREADY_MSG = "Object already has a handle"
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// portable version using 32 bit integers.
|
||||
|
||||
type portableHandleMap struct {
|
||||
sync.RWMutex
|
||||
// The generation counter is incremented each time a NodeId is reused,
|
||||
// hence the (NodeId, Generation) tuple is always unique.
|
||||
generation uint64
|
||||
// Number of currently used handles
|
||||
used int
|
||||
// Array of Go objects indexed by NodeId
|
||||
handles []*handled
|
||||
// Free slots in the "handles" array
|
||||
freeIds []uint64
|
||||
}
|
||||
|
||||
func newPortableHandleMap() *portableHandleMap {
|
||||
return &portableHandleMap{
|
||||
// Avoid handing out ID 0 and 1.
|
||||
handles: []*handled{nil, nil},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Register(obj *handled) (handle, generation uint64) {
|
||||
m.Lock()
|
||||
if obj.count == 0 {
|
||||
if obj.check != 0 {
|
||||
panic(_ALREADY_MSG)
|
||||
}
|
||||
|
||||
if len(m.freeIds) == 0 {
|
||||
handle = uint64(len(m.handles))
|
||||
m.handles = append(m.handles, obj)
|
||||
} else {
|
||||
handle = m.freeIds[len(m.freeIds)-1]
|
||||
m.freeIds = m.freeIds[:len(m.freeIds)-1]
|
||||
m.generation++
|
||||
m.handles[handle] = obj
|
||||
}
|
||||
m.used++
|
||||
obj.handle = handle
|
||||
} else {
|
||||
handle = obj.handle
|
||||
}
|
||||
obj.count++
|
||||
generation = m.generation
|
||||
m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Handle(obj *handled) (h uint64) {
|
||||
m.RLock()
|
||||
if obj.count == 0 {
|
||||
h = 0
|
||||
} else {
|
||||
h = obj.handle
|
||||
}
|
||||
m.RUnlock()
|
||||
return h
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Count() int {
|
||||
m.RLock()
|
||||
c := m.used
|
||||
m.RUnlock()
|
||||
return c
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Decode(h uint64) *handled {
|
||||
m.RLock()
|
||||
v := m.handles[h]
|
||||
m.RUnlock()
|
||||
return v
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Forget(h uint64, count int) (forgotten bool, obj *handled) {
|
||||
m.Lock()
|
||||
obj = m.handles[h]
|
||||
obj.count -= count
|
||||
if obj.count < 0 {
|
||||
log.Panicf("underflow: handle %d, count %d, object %d", h, count, obj.count)
|
||||
} else if obj.count == 0 {
|
||||
m.handles[h] = nil
|
||||
m.freeIds = append(m.freeIds, h)
|
||||
m.used--
|
||||
forgotten = true
|
||||
obj.handle = 0
|
||||
}
|
||||
m.Unlock()
|
||||
return forgotten, obj
|
||||
}
|
||||
|
||||
func (m *portableHandleMap) Has(h uint64) bool {
|
||||
m.RLock()
|
||||
ok := m.handles[h] != nil
|
||||
m.RUnlock()
|
||||
return ok
|
||||
}
|
||||
289
vendor/github.com/hanwen/go-fuse/fuse/nodefs/inode.go
generated
vendored
Normal file
289
vendor/github.com/hanwen/go-fuse/fuse/nodefs/inode.go
generated
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
type parentData struct {
|
||||
parent *Inode
|
||||
name string
|
||||
}
|
||||
|
||||
// An Inode reflects the kernel's idea of the inode. Inodes have IDs
|
||||
// that are communicated to the kernel, and they have a tree
|
||||
// structure: a directory Inode may contain named children. Each
|
||||
// Inode object is paired with a Node object, which file system
|
||||
// implementers should supply.
|
||||
type Inode struct {
|
||||
handled handled
|
||||
|
||||
// Generation number of the inode. Each (re)use of an inode
|
||||
// should have a unique generation number.
|
||||
generation uint64
|
||||
|
||||
// Number of open files and its protection.
|
||||
openFilesMutex sync.Mutex
|
||||
openFiles []*openedFile
|
||||
|
||||
fsInode Node
|
||||
|
||||
// Each inode belongs to exactly one fileSystemMount. This
|
||||
// pointer is constant during the lifetime, except upon
|
||||
// Unmount() when it is set to nil.
|
||||
mount *fileSystemMount
|
||||
|
||||
// All data below is protected by treeLock.
|
||||
children map[string]*Inode
|
||||
// Due to hard links, an Inode can have many parents.
|
||||
parents map[parentData]struct{}
|
||||
|
||||
// Non-nil if this inode is a mountpoint, ie. the Root of a
|
||||
// NodeFileSystem.
|
||||
mountPoint *fileSystemMount
|
||||
}
|
||||
|
||||
func newInode(isDir bool, fsNode Node) *Inode {
|
||||
me := new(Inode)
|
||||
me.parents = map[parentData]struct{}{}
|
||||
if isDir {
|
||||
me.children = make(map[string]*Inode, initDirSize)
|
||||
}
|
||||
me.fsInode = fsNode
|
||||
me.fsInode.SetInode(me)
|
||||
return me
|
||||
}
|
||||
|
||||
// public methods.
|
||||
|
||||
// Returns any open file, preferably a r/w one.
|
||||
func (n *Inode) AnyFile() (file File) {
|
||||
n.openFilesMutex.Lock()
|
||||
for _, f := range n.openFiles {
|
||||
if file == nil || f.WithFlags.OpenFlags&fuse.O_ANYWRITE != 0 {
|
||||
file = f.WithFlags.File
|
||||
}
|
||||
}
|
||||
n.openFilesMutex.Unlock()
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
// Children returns all children of this inode.
|
||||
func (n *Inode) Children() (out map[string]*Inode) {
|
||||
n.mount.treeLock.RLock()
|
||||
out = make(map[string]*Inode, len(n.children))
|
||||
for k, v := range n.children {
|
||||
out[k] = v
|
||||
}
|
||||
n.mount.treeLock.RUnlock()
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Parent returns a random parent and the name this inode has under this parent.
|
||||
// This function can be used to walk up the directory tree. It will not cross
|
||||
// sub-mounts.
|
||||
func (n *Inode) Parent() (parent *Inode, name string) {
|
||||
if n.mountPoint != nil {
|
||||
return nil, ""
|
||||
}
|
||||
for k := range n.parents {
|
||||
return k.parent, k.name
|
||||
}
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
// FsChildren returns all the children from the same filesystem. It
|
||||
// will skip mountpoints.
|
||||
func (n *Inode) FsChildren() (out map[string]*Inode) {
|
||||
n.mount.treeLock.RLock()
|
||||
out = map[string]*Inode{}
|
||||
for k, v := range n.children {
|
||||
if v.mount == n.mount {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
n.mount.treeLock.RUnlock()
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Node returns the file-system specific node.
|
||||
func (n *Inode) Node() Node {
|
||||
return n.fsInode
|
||||
}
|
||||
|
||||
// Files() returns an opens file that have bits in common with the
|
||||
// give mask. Use mask==0 to return all files.
|
||||
func (n *Inode) Files(mask uint32) (files []WithFlags) {
|
||||
n.openFilesMutex.Lock()
|
||||
for _, f := range n.openFiles {
|
||||
if mask == 0 || f.WithFlags.OpenFlags&mask != 0 {
|
||||
files = append(files, f.WithFlags)
|
||||
}
|
||||
}
|
||||
n.openFilesMutex.Unlock()
|
||||
return files
|
||||
}
|
||||
|
||||
// IsDir returns true if this is a directory.
|
||||
func (n *Inode) IsDir() bool {
|
||||
return n.children != nil
|
||||
}
|
||||
|
||||
// NewChild adds a new child inode to this inode.
|
||||
func (n *Inode) NewChild(name string, isDir bool, fsi Node) *Inode {
|
||||
ch := newInode(isDir, fsi)
|
||||
ch.mount = n.mount
|
||||
n.AddChild(name, ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
// GetChild returns a child inode with the given name, or nil if it
|
||||
// does not exist.
|
||||
func (n *Inode) GetChild(name string) (child *Inode) {
|
||||
n.mount.treeLock.RLock()
|
||||
child = n.children[name]
|
||||
n.mount.treeLock.RUnlock()
|
||||
|
||||
return child
|
||||
}
|
||||
|
||||
// AddChild adds a child inode. The parent inode must be a directory
|
||||
// node.
|
||||
func (n *Inode) AddChild(name string, child *Inode) {
|
||||
if child == nil {
|
||||
log.Panicf("adding nil child as %q", name)
|
||||
}
|
||||
n.mount.treeLock.Lock()
|
||||
n.addChild(name, child)
|
||||
n.mount.treeLock.Unlock()
|
||||
}
|
||||
|
||||
// TreeWatcher is an additional interface that Nodes can implement.
|
||||
// If they do, the OnAdd and OnRemove are called for operations on the
|
||||
// file system tree. These functions run under a lock, so they should
|
||||
// not do blocking operations.
|
||||
type TreeWatcher interface {
|
||||
OnAdd(parent *Inode, name string)
|
||||
OnRemove(parent *Inode, name string)
|
||||
}
|
||||
|
||||
// RmChild removes an inode by name, and returns it. It returns nil if
|
||||
// child does not exist.
|
||||
func (n *Inode) RmChild(name string) (ch *Inode) {
|
||||
n.mount.treeLock.Lock()
|
||||
ch = n.rmChild(name)
|
||||
n.mount.treeLock.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// private
|
||||
|
||||
// addChild adds "child" to our children under name "name".
|
||||
// Must be called with treeLock for the mount held.
|
||||
func (n *Inode) addChild(name string, child *Inode) {
|
||||
if paranoia {
|
||||
ch := n.children[name]
|
||||
if ch != nil {
|
||||
log.Panicf("Already have an Inode with same name: %v: %v", name, ch)
|
||||
}
|
||||
}
|
||||
n.children[name] = child
|
||||
child.parents[parentData{n, name}] = struct{}{}
|
||||
if w, ok := child.Node().(TreeWatcher); ok && child.mountPoint == nil {
|
||||
w.OnAdd(n, name)
|
||||
}
|
||||
}
|
||||
|
||||
// rmChild throws out child "name". This means (1) deleting "name" from our
|
||||
// "children" map and (2) deleting ourself from the child's "parents" map.
|
||||
// Must be called with treeLock for the mount held.
|
||||
func (n *Inode) rmChild(name string) *Inode {
|
||||
ch := n.children[name]
|
||||
if ch != nil {
|
||||
delete(n.children, name)
|
||||
delete(ch.parents, parentData{n, name})
|
||||
if w, ok := ch.Node().(TreeWatcher); ok && ch.mountPoint == nil {
|
||||
w.OnRemove(n, name)
|
||||
}
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
// Can only be called on untouched root inodes.
|
||||
func (n *Inode) mountFs(opts *Options) {
|
||||
n.mountPoint = &fileSystemMount{
|
||||
openFiles: newPortableHandleMap(),
|
||||
mountInode: n,
|
||||
options: opts,
|
||||
}
|
||||
n.mount = n.mountPoint
|
||||
}
|
||||
|
||||
// Must be called with treeLock held.
|
||||
func (n *Inode) canUnmount() bool {
|
||||
for _, v := range n.children {
|
||||
if v.mountPoint != nil {
|
||||
// This access may be out of date, but it is no
|
||||
// problem to err on the safe side.
|
||||
return false
|
||||
}
|
||||
if !v.canUnmount() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
n.openFilesMutex.Lock()
|
||||
ok := len(n.openFiles) == 0
|
||||
n.openFilesMutex.Unlock()
|
||||
return ok
|
||||
}
|
||||
|
||||
func (n *Inode) getMountDirEntries() (out []fuse.DirEntry) {
|
||||
n.mount.treeLock.RLock()
|
||||
for k, v := range n.children {
|
||||
if v.mountPoint != nil {
|
||||
out = append(out, fuse.DirEntry{
|
||||
Name: k,
|
||||
Mode: fuse.S_IFDIR,
|
||||
})
|
||||
}
|
||||
}
|
||||
n.mount.treeLock.RUnlock()
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
const initDirSize = 20
|
||||
|
||||
func (n *Inode) verify(cur *fileSystemMount) {
|
||||
n.handled.verify()
|
||||
if n.mountPoint != nil {
|
||||
if n != n.mountPoint.mountInode {
|
||||
log.Panicf("mountpoint mismatch %v %v", n, n.mountPoint.mountInode)
|
||||
}
|
||||
cur = n.mountPoint
|
||||
|
||||
cur.treeLock.Lock()
|
||||
defer cur.treeLock.Unlock()
|
||||
}
|
||||
if n.mount != cur {
|
||||
log.Panicf("n.mount not set correctly %v %v", n.mount, cur)
|
||||
}
|
||||
|
||||
for nm, ch := range n.children {
|
||||
if ch == nil {
|
||||
log.Panicf("Found nil child: %q", nm)
|
||||
}
|
||||
ch.verify(cur)
|
||||
}
|
||||
}
|
||||
109
vendor/github.com/hanwen/go-fuse/fuse/nodefs/lockingfile.go
generated
vendored
Normal file
109
vendor/github.com/hanwen/go-fuse/fuse/nodefs/lockingfile.go
generated
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
type lockingFile struct {
|
||||
mu *sync.Mutex
|
||||
file File
|
||||
}
|
||||
|
||||
// NewLockingFile serializes operations an existing File.
|
||||
func NewLockingFile(mu *sync.Mutex, f File) File {
|
||||
return &lockingFile{
|
||||
mu: mu,
|
||||
file: f,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *lockingFile) SetInode(*Inode) {
|
||||
}
|
||||
|
||||
func (f *lockingFile) InnerFile() File {
|
||||
return f.file
|
||||
}
|
||||
|
||||
func (f *lockingFile) String() string {
|
||||
return fmt.Sprintf("lockingFile(%s)", f.file.String())
|
||||
}
|
||||
|
||||
func (f *lockingFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Read(buf, off)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Write(data, off)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Flush() fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Flush()
|
||||
}
|
||||
|
||||
func (f *lockingFile) Flock(flags int) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Flock(flags)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Release() {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
f.file.Release()
|
||||
}
|
||||
|
||||
func (f *lockingFile) GetAttr(a *fuse.Attr) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.GetAttr(a)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Fsync(flags int) (code fuse.Status) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Fsync(flags)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Utimens(atime, mtime)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Truncate(size uint64) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Truncate(size)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Chown(uid uint32, gid uint32) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Chown(uid, gid)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Chmod(perms uint32) fuse.Status {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Chmod(perms)
|
||||
}
|
||||
|
||||
func (f *lockingFile) Allocate(off uint64, size uint64, mode uint32) (code fuse.Status) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.file.Allocate(off, size, mode)
|
||||
}
|
||||
232
vendor/github.com/hanwen/go-fuse/fuse/nodefs/memnode.go
generated
vendored
Normal file
232
vendor/github.com/hanwen/go-fuse/fuse/nodefs/memnode.go
generated
vendored
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// NewMemNodeFSRoot creates an in-memory node-based filesystem. Files
|
||||
// are written into a backing store under the given prefix.
|
||||
func NewMemNodeFSRoot(prefix string) Node {
|
||||
fs := &memNodeFs{
|
||||
backingStorePrefix: prefix,
|
||||
}
|
||||
fs.root = fs.newNode()
|
||||
return fs.root
|
||||
}
|
||||
|
||||
type memNodeFs struct {
|
||||
backingStorePrefix string
|
||||
root *memNode
|
||||
|
||||
mutex sync.Mutex
|
||||
nextFree int
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) String() string {
|
||||
return fmt.Sprintf("MemNodeFs(%s)", fs.backingStorePrefix)
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) Root() Node {
|
||||
return fs.root
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) SetDebug(bool) {
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) OnMount(*FileSystemConnector) {
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) OnUnmount() {
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) newNode() *memNode {
|
||||
fs.mutex.Lock()
|
||||
id := fs.nextFree
|
||||
fs.nextFree++
|
||||
fs.mutex.Unlock()
|
||||
n := &memNode{
|
||||
Node: NewDefaultNode(),
|
||||
fs: fs,
|
||||
id: id,
|
||||
}
|
||||
now := time.Now()
|
||||
n.info.SetTimes(&now, &now, &now)
|
||||
n.info.Mode = fuse.S_IFDIR | 0777
|
||||
return n
|
||||
}
|
||||
|
||||
func (fs *memNodeFs) Filename(n *Inode) string {
|
||||
mn := n.Node().(*memNode)
|
||||
return mn.filename()
|
||||
}
|
||||
|
||||
type memNode struct {
|
||||
Node
|
||||
fs *memNodeFs
|
||||
id int
|
||||
|
||||
link string
|
||||
info fuse.Attr
|
||||
}
|
||||
|
||||
func (n *memNode) filename() string {
|
||||
return fmt.Sprintf("%s%d", n.fs.backingStorePrefix, n.id)
|
||||
}
|
||||
|
||||
func (n *memNode) Deletable() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (n *memNode) Readlink(c *fuse.Context) ([]byte, fuse.Status) {
|
||||
return []byte(n.link), fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) StatFs() *fuse.StatfsOut {
|
||||
return &fuse.StatfsOut{}
|
||||
}
|
||||
|
||||
func (n *memNode) Mkdir(name string, mode uint32, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
ch := n.fs.newNode()
|
||||
ch.info.Mode = mode | fuse.S_IFDIR
|
||||
n.Inode().NewChild(name, true, ch)
|
||||
return ch.Inode(), fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
ch := n.Inode().RmChild(name)
|
||||
if ch == nil {
|
||||
return fuse.ENOENT
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return n.Unlink(name, context)
|
||||
}
|
||||
|
||||
func (n *memNode) Symlink(name string, content string, context *fuse.Context) (newNode *Inode, code fuse.Status) {
|
||||
ch := n.fs.newNode()
|
||||
ch.info.Mode = fuse.S_IFLNK | 0777
|
||||
ch.link = content
|
||||
n.Inode().NewChild(name, false, ch)
|
||||
return ch.Inode(), fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Rename(oldName string, newParent Node, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
ch := n.Inode().RmChild(oldName)
|
||||
newParent.Inode().RmChild(newName)
|
||||
newParent.Inode().AddChild(newName, ch)
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Link(name string, existing Node, context *fuse.Context) (*Inode, fuse.Status) {
|
||||
n.Inode().AddChild(name, existing.Inode())
|
||||
return existing.Inode(), fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file File, node *Inode, code fuse.Status) {
|
||||
ch := n.fs.newNode()
|
||||
ch.info.Mode = mode | fuse.S_IFREG
|
||||
|
||||
f, err := os.Create(ch.filename())
|
||||
if err != nil {
|
||||
return nil, nil, fuse.ToStatus(err)
|
||||
}
|
||||
n.Inode().NewChild(name, false, ch)
|
||||
return ch.newFile(f), ch.Inode(), fuse.OK
|
||||
}
|
||||
|
||||
type memNodeFile struct {
|
||||
File
|
||||
node *memNode
|
||||
}
|
||||
|
||||
func (n *memNodeFile) String() string {
|
||||
return fmt.Sprintf("memNodeFile(%s)", n.File.String())
|
||||
}
|
||||
|
||||
func (n *memNodeFile) InnerFile() File {
|
||||
return n.File
|
||||
}
|
||||
|
||||
func (n *memNodeFile) Flush() fuse.Status {
|
||||
code := n.File.Flush()
|
||||
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
st := syscall.Stat_t{}
|
||||
err := syscall.Stat(n.node.filename(), &st)
|
||||
n.node.info.Size = uint64(st.Size)
|
||||
n.node.info.Blocks = uint64(st.Blocks)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (n *memNode) newFile(f *os.File) File {
|
||||
return &memNodeFile{
|
||||
File: NewLoopbackFile(f),
|
||||
node: n,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *memNode) Open(flags uint32, context *fuse.Context) (file File, code fuse.Status) {
|
||||
f, err := os.OpenFile(n.filename(), int(flags), 0666)
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
return n.newFile(f), fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) GetAttr(fi *fuse.Attr, file File, context *fuse.Context) (code fuse.Status) {
|
||||
*fi = n.info
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Truncate(file File, size uint64, context *fuse.Context) (code fuse.Status) {
|
||||
if file != nil {
|
||||
code = file.Truncate(size)
|
||||
} else {
|
||||
err := os.Truncate(n.filename(), int64(size))
|
||||
code = fuse.ToStatus(err)
|
||||
}
|
||||
if code.Ok() {
|
||||
now := time.Now()
|
||||
n.info.SetTimes(nil, nil, &now)
|
||||
// TODO - should update mtime too?
|
||||
n.info.Size = size
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
func (n *memNode) Utimens(file File, atime *time.Time, mtime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
c := time.Now()
|
||||
n.info.SetTimes(atime, mtime, &c)
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Chmod(file File, perms uint32, context *fuse.Context) (code fuse.Status) {
|
||||
n.info.Mode = (n.info.Mode &^ 07777) | perms
|
||||
now := time.Now()
|
||||
n.info.SetTimes(nil, nil, &now)
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (n *memNode) Chown(file File, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
n.info.Uid = uid
|
||||
n.info.Gid = gid
|
||||
now := time.Now()
|
||||
n.info.SetTimes(nil, nil, &now)
|
||||
return fuse.OK
|
||||
}
|
||||
13
vendor/github.com/hanwen/go-fuse/fuse/nodefs/nodefs.go
generated
vendored
Normal file
13
vendor/github.com/hanwen/go-fuse/fuse/nodefs/nodefs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import "time"
|
||||
|
||||
func splitDuration(dt time.Duration, secs *uint64, nsecs *uint32) {
|
||||
ns := int64(dt)
|
||||
*nsecs = uint32(ns % 1e9)
|
||||
*secs = uint64(ns / 1e9)
|
||||
}
|
||||
18
vendor/github.com/hanwen/go-fuse/fuse/nodefs/print.go
generated
vendored
Normal file
18
vendor/github.com/hanwen/go-fuse/fuse/nodefs/print.go
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
// String provides a debug string for the given file.
|
||||
func (f *WithFlags) String() string {
|
||||
return fmt.Sprintf("File %s (%s) %s %s",
|
||||
f.File, f.Description, fuse.FlagString(fuse.OpenFlagNames, int64(f.OpenFlags), "O_RDONLY"),
|
||||
fuse.FlagString(fuse.FuseOpenFlagNames, int64(f.FuseFlags), ""))
|
||||
}
|
||||
20
vendor/github.com/hanwen/go-fuse/fuse/nodefs/syscall_linux.go
generated
vendored
Normal file
20
vendor/github.com/hanwen/go-fuse/fuse/nodefs/syscall_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package nodefs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// futimens - futimens(3) calls utimensat(2) with "pathname" set to null and
|
||||
// "flags" set to zero
|
||||
func futimens(fd int, times *[2]syscall.Timespec) (err error) {
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS_UTIMENSAT, uintptr(fd), 0, uintptr(unsafe.Pointer(times)), uintptr(0), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
658
vendor/github.com/hanwen/go-fuse/fuse/opcode.go
generated
vendored
Normal file
658
vendor/github.com/hanwen/go-fuse/fuse/opcode.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
85
vendor/github.com/hanwen/go-fuse/fuse/pathfs/api.go
generated
vendored
Normal file
85
vendor/github.com/hanwen/go-fuse/fuse/pathfs/api.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
// A filesystem API that uses paths rather than inodes. A minimal
|
||||
// file system should have at least a functional GetAttr method.
|
||||
// Typically, each call happens in its own goroutine, so take care to
|
||||
// make the file system thread-safe.
|
||||
//
|
||||
// NewDefaultFileSystem provides a null implementation of required
|
||||
// methods.
|
||||
type FileSystem interface {
|
||||
// Used for pretty printing.
|
||||
String() string
|
||||
|
||||
// If called, provide debug output through the log package.
|
||||
SetDebug(debug bool)
|
||||
|
||||
// Attributes. This function is the main entry point, through
|
||||
// which FUSE discovers which files and directories exist.
|
||||
//
|
||||
// If the filesystem wants to implement hard-links, it should
|
||||
// return consistent non-zero FileInfo.Ino data. Using
|
||||
// hardlinks incurs a performance hit.
|
||||
GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status)
|
||||
|
||||
// These should update the file's ctime too.
|
||||
Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status)
|
||||
Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status)
|
||||
Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
Truncate(name string, size uint64, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
Access(name string, mode uint32, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
// Tree structure
|
||||
Link(oldName string, newName string, context *fuse.Context) (code fuse.Status)
|
||||
Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status
|
||||
Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status
|
||||
Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status)
|
||||
Rmdir(name string, context *fuse.Context) (code fuse.Status)
|
||||
Unlink(name string, context *fuse.Context) (code fuse.Status)
|
||||
|
||||
// Extended attributes.
|
||||
GetXAttr(name string, attribute string, context *fuse.Context) (data []byte, code fuse.Status)
|
||||
ListXAttr(name string, context *fuse.Context) (attributes []string, code fuse.Status)
|
||||
RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status
|
||||
SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status
|
||||
|
||||
// Called after mount.
|
||||
OnMount(nodeFs *PathNodeFs)
|
||||
OnUnmount()
|
||||
|
||||
// File handling. If opening for writing, the file's mtime
|
||||
// should be updated too.
|
||||
Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status)
|
||||
Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status)
|
||||
|
||||
// Directory handling
|
||||
OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, code fuse.Status)
|
||||
|
||||
// Symlinks.
|
||||
Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status)
|
||||
Readlink(name string, context *fuse.Context) (string, fuse.Status)
|
||||
|
||||
StatFs(name string) *fuse.StatfsOut
|
||||
}
|
||||
|
||||
type PathNodeFsOptions struct {
|
||||
// If ClientInodes is set, use Inode returned from GetAttr to
|
||||
// find hard-linked files.
|
||||
ClientInodes bool
|
||||
|
||||
// Debug controls printing of debug information.
|
||||
Debug bool
|
||||
}
|
||||
61
vendor/github.com/hanwen/go-fuse/fuse/pathfs/copy.go
generated
vendored
Normal file
61
vendor/github.com/hanwen/go-fuse/fuse/pathfs/copy.go
generated
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
func CopyFile(srcFs, destFs FileSystem, srcFile, destFile string, context *fuse.Context) fuse.Status {
|
||||
src, code := srcFs.Open(srcFile, uint32(os.O_RDONLY), context)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
defer src.Release()
|
||||
defer src.Flush()
|
||||
|
||||
attr, code := srcFs.GetAttr(srcFile, context)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
dst, code := destFs.Create(destFile, uint32(os.O_WRONLY|os.O_CREATE|os.O_TRUNC), attr.Mode, context)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
defer dst.Release()
|
||||
defer dst.Flush()
|
||||
|
||||
buf := make([]byte, 128*(1<<10))
|
||||
off := int64(0)
|
||||
for {
|
||||
res, code := src.Read(buf, off)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
data, code := res.Bytes(buf)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
|
||||
if len(data) == 0 {
|
||||
break
|
||||
}
|
||||
n, code := dst.Write(data, off)
|
||||
if !code.Ok() {
|
||||
return code
|
||||
}
|
||||
if int(n) < len(data) {
|
||||
return fuse.EIO
|
||||
}
|
||||
if len(data) < len(buf) {
|
||||
break
|
||||
}
|
||||
off += int64(len(data))
|
||||
}
|
||||
return fuse.OK
|
||||
}
|
||||
122
vendor/github.com/hanwen/go-fuse/fuse/pathfs/default.go
generated
vendored
Normal file
122
vendor/github.com/hanwen/go-fuse/fuse/pathfs/default.go
generated
vendored
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
// NewDefaultFileSystem creates a filesystem that responds ENOSYS for
|
||||
// all methods
|
||||
func NewDefaultFileSystem() FileSystem {
|
||||
return (*defaultFileSystem)(nil)
|
||||
}
|
||||
|
||||
// defaultFileSystem implements a FileSystem that returns ENOSYS for every operation.
|
||||
type defaultFileSystem struct{}
|
||||
|
||||
func (fs *defaultFileSystem) SetDebug(debug bool) {}
|
||||
|
||||
// defaultFileSystem
|
||||
func (fs *defaultFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
return nil, fuse.ENOATTR
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
|
||||
return "", fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) OnMount(nodeFs *PathNodeFs) {
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) OnUnmount() {
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
return nil, fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ENOSYS
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) String() string {
|
||||
return "defaultFileSystem"
|
||||
}
|
||||
|
||||
func (fs *defaultFileSystem) StatFs(name string) *fuse.StatfsOut {
|
||||
return nil
|
||||
}
|
||||
167
vendor/github.com/hanwen/go-fuse/fuse/pathfs/locking.go
generated
vendored
Normal file
167
vendor/github.com/hanwen/go-fuse/fuse/pathfs/locking.go
generated
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
type lockingFileSystem struct {
|
||||
// Should be public so people reusing can access the wrapped
|
||||
// FS.
|
||||
FS FileSystem
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// NewLockingFileSystem is a wrapper that makes a FileSystem
|
||||
// threadsafe by serializing each operation.
|
||||
func NewLockingFileSystem(pfs FileSystem) FileSystem {
|
||||
l := new(lockingFileSystem)
|
||||
l.FS = pfs
|
||||
return l
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) String() string {
|
||||
defer fs.locked()()
|
||||
return fs.FS.String()
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) SetDebug(debug bool) {
|
||||
defer fs.locked()()
|
||||
fs.FS.SetDebug(debug)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) StatFs(name string) *fuse.StatfsOut {
|
||||
defer fs.locked()()
|
||||
return fs.FS.StatFs(name)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) locked() func() {
|
||||
fs.lock.Lock()
|
||||
return func() { fs.lock.Unlock() }
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.GetAttr(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Readlink(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Mknod(name, mode, dev, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Mkdir(name, mode, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Unlink(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Rmdir(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Symlink(value, linkName, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Rename(oldName, newName, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Link(oldName, newName, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Chmod(name, mode, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Chown(name, uid, gid, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Truncate(name, offset, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
file, code = fs.FS.Open(name, flags, context)
|
||||
file = nodefs.NewLockingFile(&fs.lock, file)
|
||||
return
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.OpenDir(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) OnMount(nodeFs *PathNodeFs) {
|
||||
defer fs.locked()()
|
||||
fs.FS.OnMount(nodeFs)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) OnUnmount() {
|
||||
defer fs.locked()()
|
||||
fs.FS.OnUnmount()
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Access(name, mode, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
file, code = fs.FS.Create(name, flags, mode, context)
|
||||
|
||||
file = nodefs.NewLockingFile(&fs.lock, file)
|
||||
return file, code
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.Utimens(name, Atime, Mtime, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.GetXAttr(name, attr, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
defer fs.locked()()
|
||||
return fs.FS.SetXAttr(name, attr, data, flags, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
|
||||
defer fs.locked()()
|
||||
return fs.FS.ListXAttr(name, context)
|
||||
}
|
||||
|
||||
func (fs *lockingFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
|
||||
defer fs.locked()()
|
||||
return fs.FS.RemoveXAttr(name, attr, context)
|
||||
}
|
||||
183
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback.go
generated
vendored
Normal file
183
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback.go
generated
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
type loopbackFileSystem struct {
|
||||
// TODO - this should need default fill in.
|
||||
FileSystem
|
||||
Root string
|
||||
}
|
||||
|
||||
// A FUSE filesystem that shunts all request to an underlying file
|
||||
// system. Its main purpose is to provide test coverage without
|
||||
// having to build a synthetic filesystem.
|
||||
func NewLoopbackFileSystem(root string) FileSystem {
|
||||
// Make sure the Root path is absolute to avoid problems when the
|
||||
// application changes working directory.
|
||||
root, err := filepath.Abs(root)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &loopbackFileSystem{
|
||||
FileSystem: NewDefaultFileSystem(),
|
||||
Root: root,
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) StatFs(name string) *fuse.StatfsOut {
|
||||
s := syscall.Statfs_t{}
|
||||
err := syscall.Statfs(fs.GetPath(name), &s)
|
||||
if err == nil {
|
||||
out := &fuse.StatfsOut{}
|
||||
out.FromStatfsT(&s)
|
||||
return out
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) OnMount(nodeFs *PathNodeFs) {
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) OnUnmount() {}
|
||||
|
||||
func (fs *loopbackFileSystem) GetPath(relPath string) string {
|
||||
return filepath.Join(fs.Root, relPath)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) GetAttr(name string, context *fuse.Context) (a *fuse.Attr, code fuse.Status) {
|
||||
fullPath := fs.GetPath(name)
|
||||
var err error = nil
|
||||
st := syscall.Stat_t{}
|
||||
if name == "" {
|
||||
// When GetAttr is called for the toplevel directory, we always want
|
||||
// to look through symlinks.
|
||||
err = syscall.Stat(fullPath, &st)
|
||||
} else {
|
||||
err = syscall.Lstat(fullPath, &st)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
a = &fuse.Attr{}
|
||||
a.FromStat(&st)
|
||||
return a, fuse.OK
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
// What other ways beyond O_RDONLY are there to open
|
||||
// directories?
|
||||
f, err := os.Open(fs.GetPath(name))
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
want := 500
|
||||
output := make([]fuse.DirEntry, 0, want)
|
||||
for {
|
||||
infos, err := f.Readdir(want)
|
||||
for i := range infos {
|
||||
// workaround forhttps://code.google.com/p/go/issues/detail?id=5960
|
||||
if infos[i] == nil {
|
||||
continue
|
||||
}
|
||||
n := infos[i].Name()
|
||||
d := fuse.DirEntry{
|
||||
Name: n,
|
||||
}
|
||||
if s := fuse.ToStatT(infos[i]); s != nil {
|
||||
d.Mode = uint32(s.Mode)
|
||||
} else {
|
||||
log.Printf("ReadDir entry %q for %q has no stat info", n, name)
|
||||
}
|
||||
output = append(output, d)
|
||||
}
|
||||
if len(infos) < want || err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Println("Readdir() returned err:", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
f.Close()
|
||||
|
||||
return output, fuse.OK
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Open(name string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) {
|
||||
f, err := os.OpenFile(fs.GetPath(name), int(flags), 0)
|
||||
if err != nil {
|
||||
return nil, fuse.ToStatus(err)
|
||||
}
|
||||
return nodefs.NewLoopbackFile(f), fuse.OK
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
err := os.Chmod(fs.GetPath(path), os.FileMode(mode))
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Chown(path string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(os.Chown(fs.GetPath(path), int(uid), int(gid)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Truncate(path string, offset uint64, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(os.Truncate(fs.GetPath(path), int64(offset)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Readlink(name string, context *fuse.Context) (out string, code fuse.Status) {
|
||||
f, err := os.Readlink(fs.GetPath(name))
|
||||
return f, fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(syscall.Mknod(fs.GetPath(name), mode, int(dev)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Mkdir(path string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(os.Mkdir(fs.GetPath(path), os.FileMode(mode)))
|
||||
}
|
||||
|
||||
// Don't use os.Remove, it removes twice (unlink followed by rmdir).
|
||||
func (fs *loopbackFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(syscall.Unlink(fs.GetPath(name)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(syscall.Rmdir(fs.GetPath(name)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Symlink(pointedTo string, linkName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(os.Symlink(pointedTo, fs.GetPath(linkName)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Rename(oldPath string, newPath string, context *fuse.Context) (codee fuse.Status) {
|
||||
err := os.Rename(fs.GetPath(oldPath), fs.GetPath(newPath))
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Link(orig string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(os.Link(fs.GetPath(orig), fs.GetPath(newName)))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.ToStatus(syscall.Access(fs.GetPath(name), mode))
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) Create(path string, flags uint32, mode uint32, context *fuse.Context) (fuseFile nodefs.File, code fuse.Status) {
|
||||
f, err := os.OpenFile(fs.GetPath(path), int(flags)|os.O_CREATE, os.FileMode(mode))
|
||||
return nodefs.NewLoopbackFile(f), fuse.ToStatus(err)
|
||||
}
|
||||
47
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback_darwin.go
generated
vendored
Normal file
47
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
const _UTIME_NOW = ((1 << 30) - 1)
|
||||
const _UTIME_OMIT = ((1 << 30) - 2)
|
||||
|
||||
// timeToTimeval - Convert time.Time to syscall.Timeval
|
||||
//
|
||||
// Note: This does not use syscall.NsecToTimespec because
|
||||
// that does not work properly for times before 1970,
|
||||
// see https://github.com/golang/go/issues/12777
|
||||
func timeToTimeval(t *time.Time) syscall.Timeval {
|
||||
var tv syscall.Timeval
|
||||
tv.Usec = int32(t.Nanosecond() / 1000)
|
||||
tv.Sec = t.Unix()
|
||||
return tv
|
||||
}
|
||||
|
||||
// OSX does not have the utimensat syscall neded to implement this properly.
|
||||
// We do our best to emulate it using futimes.
|
||||
func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Context) fuse.Status {
|
||||
tv := make([]syscall.Timeval, 2)
|
||||
if a == nil {
|
||||
tv[0].Usec = _UTIME_OMIT
|
||||
} else {
|
||||
tv[0] = timeToTimeval(a)
|
||||
}
|
||||
|
||||
if m == nil {
|
||||
tv[1].Usec = _UTIME_OMIT
|
||||
} else {
|
||||
tv[1] = timeToTimeval(m)
|
||||
}
|
||||
|
||||
err := syscall.Utimes(fs.GetPath(path), tv)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
49
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback_linux.go
generated
vendored
Normal file
49
vendor/github.com/hanwen/go-fuse/fuse/pathfs/loopback_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
)
|
||||
|
||||
func (fs *loopbackFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
|
||||
data, err := listXAttr(fs.GetPath(name))
|
||||
|
||||
return data, fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
|
||||
err := sysRemovexattr(fs.GetPath(name), attr)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) String() string {
|
||||
return fmt.Sprintf("LoopbackFs(%s)", fs.Root)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
data := make([]byte, 1024)
|
||||
data, err := getXAttr(fs.GetPath(name), attr, data)
|
||||
|
||||
return data, fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
func (fs *loopbackFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
err := syscall.Setxattr(fs.GetPath(name), attr, data, flags)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
||||
// Utimens - path based version of loopbackFile.Utimens()
|
||||
func (fs *loopbackFileSystem) Utimens(path string, a *time.Time, m *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
var ts [2]syscall.Timespec
|
||||
ts[0] = fuse.UtimeToTimespec(a)
|
||||
ts[1] = fuse.UtimeToTimespec(m)
|
||||
err := sysUtimensat(0, fs.GetPath(path), &ts, _AT_SYMLINK_NOFOLLOW)
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
741
vendor/github.com/hanwen/go-fuse/fuse/pathfs/pathfs.go
generated
vendored
Normal file
741
vendor/github.com/hanwen/go-fuse/fuse/pathfs/pathfs.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
132
vendor/github.com/hanwen/go-fuse/fuse/pathfs/prefixfs.go
generated
vendored
Normal file
132
vendor/github.com/hanwen/go-fuse/fuse/pathfs/prefixfs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
// PrefixFileSystem adds a path prefix to incoming calls.
|
||||
type prefixFileSystem struct {
|
||||
FileSystem FileSystem
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func NewPrefixFileSystem(fs FileSystem, prefix string) FileSystem {
|
||||
return &prefixFileSystem{fs, prefix}
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) SetDebug(debug bool) {
|
||||
fs.FileSystem.SetDebug(debug)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) prefixed(n string) string {
|
||||
return filepath.Join(fs.Prefix, n)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
return fs.FileSystem.GetAttr(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
|
||||
return fs.FileSystem.Readlink(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
|
||||
return fs.FileSystem.Mknod(fs.prefixed(name), mode, dev, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
|
||||
return fs.FileSystem.Mkdir(fs.prefixed(name), mode, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Unlink(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Rmdir(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Symlink(value, fs.prefixed(linkName), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Rename(fs.prefixed(oldName), fs.prefixed(newName), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Link(fs.prefixed(oldName), fs.prefixed(newName), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Chmod(fs.prefixed(name), mode, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Chown(fs.prefixed(name), uid, gid, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Truncate(fs.prefixed(name), offset, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
return fs.FileSystem.Open(fs.prefixed(name), flags, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
return fs.FileSystem.OpenDir(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) OnMount(nodeFs *PathNodeFs) {
|
||||
fs.FileSystem.OnMount(nodeFs)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) OnUnmount() {
|
||||
fs.FileSystem.OnUnmount()
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Access(fs.prefixed(name), mode, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
return fs.FileSystem.Create(fs.prefixed(name), flags, mode, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) Utimens(name string, Atime *time.Time, Mtime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Utimens(fs.prefixed(name), Atime, Mtime, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
return fs.FileSystem.GetXAttr(fs.prefixed(name), attr, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
return fs.FileSystem.SetXAttr(fs.prefixed(name), attr, data, flags, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
|
||||
return fs.FileSystem.ListXAttr(fs.prefixed(name), context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
|
||||
return fs.FileSystem.RemoveXAttr(fs.prefixed(name), attr, context)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) String() string {
|
||||
return fmt.Sprintf("prefixFileSystem(%s,%s)", fs.FileSystem.String(), fs.Prefix)
|
||||
}
|
||||
|
||||
func (fs *prefixFileSystem) StatFs(name string) *fuse.StatfsOut {
|
||||
return fs.FileSystem.StatFs(fs.prefixed(name))
|
||||
}
|
||||
123
vendor/github.com/hanwen/go-fuse/fuse/pathfs/readonlyfs.go
generated
vendored
Normal file
123
vendor/github.com/hanwen/go-fuse/fuse/pathfs/readonlyfs.go
generated
vendored
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
)
|
||||
|
||||
// NewReadonlyFileSystem returns a wrapper that only exposes read-only
|
||||
// operations.
|
||||
func NewReadonlyFileSystem(fs FileSystem) FileSystem {
|
||||
return &readonlyFileSystem{fs}
|
||||
}
|
||||
|
||||
type readonlyFileSystem struct {
|
||||
FileSystem
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
return fs.FileSystem.GetAttr(name, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Readlink(name string, context *fuse.Context) (string, fuse.Status) {
|
||||
return fs.FileSystem.Readlink(name, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Mknod(name string, mode uint32, dev uint32, context *fuse.Context) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Unlink(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Symlink(value string, linkName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Link(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Chmod(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Chown(name string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Truncate(name string, offset uint64, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
if flags&fuse.O_ANYWRITE != 0 {
|
||||
return nil, fuse.EPERM
|
||||
}
|
||||
file, code = fs.FileSystem.Open(name, flags, context)
|
||||
return nodefs.NewReadOnlyFile(file), code
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) OpenDir(name string, context *fuse.Context) (stream []fuse.DirEntry, status fuse.Status) {
|
||||
return fs.FileSystem.OpenDir(name, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) OnMount(nodeFs *PathNodeFs) {
|
||||
fs.FileSystem.OnMount(nodeFs)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) OnUnmount() {
|
||||
fs.FileSystem.OnUnmount()
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) String() string {
|
||||
return fmt.Sprintf("readonlyFileSystem(%v)", fs.FileSystem)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Access(name string, mode uint32, context *fuse.Context) (code fuse.Status) {
|
||||
return fs.FileSystem.Access(name, mode, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
return nil, fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) Utimens(name string, atime *time.Time, ctime *time.Time, context *fuse.Context) (code fuse.Status) {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) GetXAttr(name string, attr string, context *fuse.Context) ([]byte, fuse.Status) {
|
||||
return fs.FileSystem.GetXAttr(name, attr, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) SetXAttr(name string, attr string, data []byte, flags int, context *fuse.Context) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) ListXAttr(name string, context *fuse.Context) ([]string, fuse.Status) {
|
||||
return fs.FileSystem.ListXAttr(name, context)
|
||||
}
|
||||
|
||||
func (fs *readonlyFileSystem) RemoveXAttr(name string, attr string, context *fuse.Context) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
144
vendor/github.com/hanwen/go-fuse/fuse/pathfs/syscall_linux.go
generated
vendored
Normal file
144
vendor/github.com/hanwen/go-fuse/fuse/pathfs/syscall_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pathfs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var _zero uintptr
|
||||
|
||||
func getXAttr(path string, attr string, dest []byte) (value []byte, err error) {
|
||||
sz, err := sysGetxattr(path, attr, dest)
|
||||
for sz > cap(dest) && err == nil {
|
||||
dest = make([]byte, sz)
|
||||
sz, err = sysGetxattr(path, attr, dest)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dest[:sz], err
|
||||
}
|
||||
|
||||
func listXAttr(path string) (attributes []string, err error) {
|
||||
dest := make([]byte, 0)
|
||||
sz, err := sysListxattr(path, dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for sz > cap(dest) && err == nil {
|
||||
dest = make([]byte, sz)
|
||||
sz, err = sysListxattr(path, dest)
|
||||
}
|
||||
|
||||
if sz == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// -1 to drop the final empty slice.
|
||||
dest = dest[:sz-1]
|
||||
attributesBytes := bytes.Split(dest, []byte{0})
|
||||
attributes = make([]string, len(attributesBytes))
|
||||
for i, v := range attributesBytes {
|
||||
attributes[i] = string(v)
|
||||
}
|
||||
return attributes, err
|
||||
}
|
||||
|
||||
// Below is cut & paste from std lib syscall, so gccgo 4.8.1 can
|
||||
// compile this too.
|
||||
func sysGetxattr(path string, attr string, dest []byte) (sz int, err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *byte
|
||||
_p1, err = syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p2 unsafe.Pointer
|
||||
if len(dest) > 0 {
|
||||
_p2 = unsafe.Pointer(&dest[0])
|
||||
} else {
|
||||
_p2 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
|
||||
sz = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sysRemovexattr(path string, attr string) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p1 *byte
|
||||
_p1, err = syscall.BytePtrFromString(attr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _, e1 := syscall.Syscall(syscall.SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sysListxattr(path string, dest []byte) (sz int, err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = syscall.BytePtrFromString(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var _p1 unsafe.Pointer
|
||||
if len(dest) > 0 {
|
||||
_p1 = unsafe.Pointer(&dest[0])
|
||||
} else {
|
||||
_p1 = unsafe.Pointer(&_zero)
|
||||
}
|
||||
r0, _, e1 := syscall.Syscall(syscall.SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
|
||||
sz = int(r0)
|
||||
if e1 != 0 {
|
||||
err = e1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func sysSetxattr(path string, attr string, val []byte, flag int) error {
|
||||
return syscall.Setxattr(path, attr, val, flag)
|
||||
}
|
||||
|
||||
const _AT_SYMLINK_NOFOLLOW = 0x100
|
||||
|
||||
// Linux kernel syscall utimensat(2)
|
||||
//
|
||||
// Needed to implement SetAttr on symlinks correctly as only utimensat provides
|
||||
// AT_SYMLINK_NOFOLLOW.
|
||||
func sysUtimensat(dirfd int, pathname string, times *[2]syscall.Timespec, flags int) (err error) {
|
||||
|
||||
// Null-terminated version of pathname
|
||||
p0, err := syscall.BytePtrFromString(pathname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, _, e1 := syscall.Syscall6(syscall.SYS_UTIMENSAT,
|
||||
uintptr(dirfd), uintptr(unsafe.Pointer(p0)), uintptr(unsafe.Pointer(times)), uintptr(flags), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
250
vendor/github.com/hanwen/go-fuse/fuse/print.go
generated
vendored
Normal file
250
vendor/github.com/hanwen/go-fuse/fuse/print.go
generated
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var initFlagNames map[int64]string
|
||||
var releaseFlagNames map[int64]string
|
||||
var OpenFlagNames map[int64]string
|
||||
var FuseOpenFlagNames map[int64]string
|
||||
var accessFlagName map[int64]string
|
||||
var writeFlagNames map[int64]string
|
||||
var readFlagNames map[int64]string
|
||||
|
||||
func init() {
|
||||
writeFlagNames = map[int64]string{
|
||||
WRITE_CACHE: "CACHE",
|
||||
WRITE_LOCKOWNER: "LOCKOWNER",
|
||||
}
|
||||
readFlagNames = map[int64]string{
|
||||
READ_LOCKOWNER: "LOCKOWNER",
|
||||
}
|
||||
initFlagNames = map[int64]string{
|
||||
CAP_ASYNC_READ: "ASYNC_READ",
|
||||
CAP_POSIX_LOCKS: "POSIX_LOCKS",
|
||||
CAP_FILE_OPS: "FILE_OPS",
|
||||
CAP_ATOMIC_O_TRUNC: "ATOMIC_O_TRUNC",
|
||||
CAP_EXPORT_SUPPORT: "EXPORT_SUPPORT",
|
||||
CAP_BIG_WRITES: "BIG_WRITES",
|
||||
CAP_DONT_MASK: "DONT_MASK",
|
||||
CAP_SPLICE_WRITE: "SPLICE_WRITE",
|
||||
CAP_SPLICE_MOVE: "SPLICE_MOVE",
|
||||
CAP_SPLICE_READ: "SPLICE_READ",
|
||||
CAP_FLOCK_LOCKS: "FLOCK_LOCKS",
|
||||
CAP_IOCTL_DIR: "IOCTL_DIR",
|
||||
CAP_AUTO_INVAL_DATA: "AUTO_INVAL_DATA",
|
||||
CAP_READDIRPLUS: "READDIRPLUS",
|
||||
CAP_READDIRPLUS_AUTO: "READDIRPLUS_AUTO",
|
||||
CAP_ASYNC_DIO: "ASYNC_DIO",
|
||||
CAP_WRITEBACK_CACHE: "WRITEBACK_CACHE",
|
||||
CAP_NO_OPEN_SUPPORT: "NO_OPEN_SUPPORT",
|
||||
}
|
||||
releaseFlagNames = map[int64]string{
|
||||
RELEASE_FLUSH: "FLUSH",
|
||||
}
|
||||
OpenFlagNames = map[int64]string{
|
||||
int64(os.O_WRONLY): "WRONLY",
|
||||
int64(os.O_RDWR): "RDWR",
|
||||
int64(os.O_APPEND): "APPEND",
|
||||
int64(syscall.O_ASYNC): "ASYNC",
|
||||
int64(os.O_CREATE): "CREAT",
|
||||
int64(os.O_EXCL): "EXCL",
|
||||
int64(syscall.O_NOCTTY): "NOCTTY",
|
||||
int64(syscall.O_NONBLOCK): "NONBLOCK",
|
||||
int64(os.O_SYNC): "SYNC",
|
||||
int64(os.O_TRUNC): "TRUNC",
|
||||
|
||||
int64(syscall.O_CLOEXEC): "CLOEXEC",
|
||||
int64(syscall.O_DIRECTORY): "DIRECTORY",
|
||||
}
|
||||
FuseOpenFlagNames = map[int64]string{
|
||||
FOPEN_DIRECT_IO: "DIRECT",
|
||||
FOPEN_KEEP_CACHE: "CACHE",
|
||||
FOPEN_NONSEEKABLE: "NONSEEK",
|
||||
}
|
||||
accessFlagName = map[int64]string{
|
||||
X_OK: "x",
|
||||
W_OK: "w",
|
||||
R_OK: "r",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func FlagString(names map[int64]string, fl int64, def string) string {
|
||||
s := []string{}
|
||||
for k, v := range names {
|
||||
if fl&k != 0 {
|
||||
s = append(s, v)
|
||||
fl ^= k
|
||||
}
|
||||
}
|
||||
if len(s) == 0 && def != "" {
|
||||
s = []string{def}
|
||||
}
|
||||
if fl != 0 {
|
||||
s = append(s, fmt.Sprintf("0x%x", fl))
|
||||
}
|
||||
|
||||
return strings.Join(s, ",")
|
||||
}
|
||||
|
||||
func (me *ForgetIn) string() string {
|
||||
return fmt.Sprintf("{Nlookup=%d}", me.Nlookup)
|
||||
}
|
||||
|
||||
func (me *_BatchForgetIn) string() string {
|
||||
return fmt.Sprintf("{Count=%d}", me.Count)
|
||||
}
|
||||
|
||||
func (me *MkdirIn) string() string {
|
||||
return fmt.Sprintf("{0%o (0%o)}", me.Mode, me.Umask)
|
||||
}
|
||||
|
||||
func (me *RenameIn) string() string {
|
||||
return fmt.Sprintf("{%d}", me.Newdir)
|
||||
}
|
||||
|
||||
func (me *SetAttrIn) string() string {
|
||||
s := []string{}
|
||||
if me.Valid&FATTR_MODE != 0 {
|
||||
s = append(s, fmt.Sprintf("mode 0%o", me.Mode))
|
||||
}
|
||||
if me.Valid&FATTR_UID != 0 {
|
||||
s = append(s, fmt.Sprintf("uid %d", me.Uid))
|
||||
}
|
||||
if me.Valid&FATTR_GID != 0 {
|
||||
s = append(s, fmt.Sprintf("uid %d", me.Gid))
|
||||
}
|
||||
if me.Valid&FATTR_SIZE != 0 {
|
||||
s = append(s, fmt.Sprintf("size %d", me.Size))
|
||||
}
|
||||
if me.Valid&FATTR_ATIME != 0 {
|
||||
s = append(s, fmt.Sprintf("atime %d.%09d", me.Atime, me.Atimensec))
|
||||
}
|
||||
if me.Valid&FATTR_MTIME != 0 {
|
||||
s = append(s, fmt.Sprintf("mtime %d.%09d", me.Mtime, me.Mtimensec))
|
||||
}
|
||||
if me.Valid&FATTR_FH != 0 {
|
||||
s = append(s, fmt.Sprintf("fh %d", me.Fh))
|
||||
}
|
||||
// TODO - FATTR_ATIME_NOW = (1 << 7), FATTR_MTIME_NOW = (1 << 8), FATTR_LOCKOWNER = (1 << 9)
|
||||
return fmt.Sprintf("{%s}", strings.Join(s, ", "))
|
||||
}
|
||||
|
||||
func (me *ReleaseIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d %s %s L%d}",
|
||||
me.Fh, FlagString(OpenFlagNames, int64(me.Flags), ""),
|
||||
FlagString(releaseFlagNames, int64(me.ReleaseFlags), ""),
|
||||
me.LockOwner)
|
||||
}
|
||||
|
||||
func (me *OpenIn) string() string {
|
||||
return fmt.Sprintf("{%s}", FlagString(OpenFlagNames, int64(me.Flags), "O_RDONLY"))
|
||||
}
|
||||
|
||||
func (me *OpenOut) string() string {
|
||||
return fmt.Sprintf("{Fh %d %s}", me.Fh,
|
||||
FlagString(FuseOpenFlagNames, int64(me.OpenFlags), ""))
|
||||
}
|
||||
|
||||
func (me *InitIn) string() string {
|
||||
return fmt.Sprintf("{%d.%d Ra 0x%x %s}",
|
||||
me.Major, me.Minor, me.MaxReadAhead,
|
||||
FlagString(initFlagNames, int64(me.Flags), ""))
|
||||
}
|
||||
|
||||
func (me *InitOut) string() string {
|
||||
return fmt.Sprintf("{%d.%d Ra 0x%x %s %d/%d Wr 0x%x Tg 0x%x}",
|
||||
me.Major, me.Minor, me.MaxReadAhead,
|
||||
FlagString(initFlagNames, int64(me.Flags), ""),
|
||||
me.CongestionThreshold, me.MaxBackground, me.MaxWrite,
|
||||
me.TimeGran)
|
||||
}
|
||||
|
||||
func (s *FsyncIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d Flags %x}", s.Fh, s.FsyncFlags)
|
||||
}
|
||||
|
||||
func (me *SetXAttrIn) string() string {
|
||||
return fmt.Sprintf("{sz %d f%o}", me.Size, me.Flags)
|
||||
}
|
||||
|
||||
func (me *GetXAttrIn) string() string {
|
||||
return fmt.Sprintf("{sz %d}", me.Size)
|
||||
}
|
||||
|
||||
func (me *GetXAttrOut) string() string {
|
||||
return fmt.Sprintf("{sz %d}", me.Size)
|
||||
}
|
||||
|
||||
func (me *AccessIn) string() string {
|
||||
return fmt.Sprintf("{%s}", FlagString(accessFlagName, int64(me.Mask), ""))
|
||||
}
|
||||
|
||||
func (me *FlushIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d}", me.Fh)
|
||||
}
|
||||
|
||||
func (me *AttrOut) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{A%d.%09d %v}",
|
||||
me.AttrValid, me.AttrValidNsec, &me.Attr)
|
||||
}
|
||||
|
||||
// Returned by LOOKUP
|
||||
func (me *EntryOut) string() string {
|
||||
return fmt.Sprintf("{NodeId: %d Generation=%d EntryValid=%d.%03d AttrValid=%d.%03d Attr=%v}",
|
||||
me.NodeId, me.Generation, me.EntryValid, me.EntryValidNsec/1000000,
|
||||
me.AttrValid, me.AttrValidNsec/1000000, &me.Attr)
|
||||
}
|
||||
|
||||
func (me *CreateOut) string() string {
|
||||
return fmt.Sprintf("{NodeId: %d Generation=%d %v %v}", me.NodeId, me.Generation, &me.EntryOut, &me.OpenOut)
|
||||
}
|
||||
|
||||
func (me *StatfsOut) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{blocks (%d,%d)/%d files %d/%d bs%d nl%d frs%d}",
|
||||
me.Bfree, me.Bavail, me.Blocks, me.Ffree, me.Files,
|
||||
me.Bsize, me.NameLen, me.Frsize)
|
||||
}
|
||||
|
||||
func (o *NotifyInvalEntryOut) string() string {
|
||||
return fmt.Sprintf("{parent %d sz %d}", o.Parent, o.NameLen)
|
||||
}
|
||||
|
||||
func (o *NotifyInvalInodeOut) string() string {
|
||||
return fmt.Sprintf("{ino %d off %d sz %d}", o.Ino, o.Off, o.Length)
|
||||
}
|
||||
|
||||
func (o *NotifyInvalDeleteOut) string() string {
|
||||
return fmt.Sprintf("{parent %d ch %d sz %d}", o.Parent, o.Child, o.NameLen)
|
||||
}
|
||||
|
||||
func (f *FallocateIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d off %d sz %d mod 0%o}",
|
||||
f.Fh, f.Offset, f.Length, f.Mode)
|
||||
}
|
||||
|
||||
func (f *LinkIn) string() string {
|
||||
return fmt.Sprintf("{Oldnodeid: %d}", f.Oldnodeid)
|
||||
}
|
||||
|
||||
// Print pretty prints FUSE data types for kernel communication
|
||||
func Print(obj interface{}) string {
|
||||
t, ok := obj.(interface {
|
||||
string() string
|
||||
})
|
||||
if ok {
|
||||
return t.string()
|
||||
}
|
||||
return fmt.Sprintf("%T: %v", obj, obj)
|
||||
}
|
||||
54
vendor/github.com/hanwen/go-fuse/fuse/print_darwin.go
generated
vendored
Normal file
54
vendor/github.com/hanwen/go-fuse/fuse/print_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func init() {
|
||||
initFlagNames[CAP_XTIMES] = "XTIMES"
|
||||
initFlagNames[CAP_VOL_RENAME] = "VOL_RENAME"
|
||||
initFlagNames[CAP_CASE_INSENSITIVE] = "CASE_INSENSITIVE"
|
||||
}
|
||||
|
||||
func (a *Attr) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{M0%o SZ=%d L=%d "+
|
||||
"%d:%d "+
|
||||
"%d %d:%d "+
|
||||
"A %d.%09d "+
|
||||
"M %d.%09d "+
|
||||
"C %d.%09d}",
|
||||
a.Mode, a.Size, a.Nlink,
|
||||
a.Uid, a.Gid,
|
||||
a.Blocks,
|
||||
a.Rdev, a.Ino, a.Atime, a.Atimensec, a.Mtime, a.Mtimensec,
|
||||
a.Ctime, a.Ctimensec)
|
||||
}
|
||||
|
||||
func (me *CreateIn) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{0%o [%s]}", me.Mode,
|
||||
FlagString(OpenFlagNames, int64(me.Flags), "O_RDONLY"))
|
||||
}
|
||||
|
||||
func (me *GetAttrIn) string() string { return "" }
|
||||
|
||||
func (me *MknodIn) string() string {
|
||||
return fmt.Sprintf("{0%o, %d}", me.Mode, me.Rdev)
|
||||
}
|
||||
|
||||
func (me *ReadIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d off %d sz %d %s}",
|
||||
me.Fh, me.Offset, me.Size,
|
||||
FlagString(readFlagNames, int64(me.ReadFlags), ""))
|
||||
}
|
||||
|
||||
func (me *WriteIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d off %d sz %d %s}",
|
||||
me.Fh, me.Offset, me.Size,
|
||||
FlagString(writeFlagNames, int64(me.WriteFlags), ""))
|
||||
}
|
||||
62
vendor/github.com/hanwen/go-fuse/fuse/print_linux.go
generated
vendored
Normal file
62
vendor/github.com/hanwen/go-fuse/fuse/print_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
OpenFlagNames[syscall.O_DIRECT] = "DIRECT"
|
||||
OpenFlagNames[syscall.O_LARGEFILE] = "LARGEFILE"
|
||||
OpenFlagNames[syscall_O_NOATIME] = "NOATIME"
|
||||
|
||||
}
|
||||
|
||||
func (a *Attr) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{M0%o SZ=%d L=%d "+
|
||||
"%d:%d "+
|
||||
"B%d*%d i%d:%d "+
|
||||
"A %d.%09d "+
|
||||
"M %d.%09d "+
|
||||
"C %d.%09d}",
|
||||
a.Mode, a.Size, a.Nlink,
|
||||
a.Uid, a.Gid,
|
||||
a.Blocks, a.Blksize,
|
||||
a.Rdev, a.Ino, a.Atime, a.Atimensec, a.Mtime, a.Mtimensec,
|
||||
a.Ctime, a.Ctimensec)
|
||||
}
|
||||
|
||||
func (me *CreateIn) string() string {
|
||||
return fmt.Sprintf(
|
||||
"{0%o [%s] (0%o)}", me.Mode,
|
||||
FlagString(OpenFlagNames, int64(me.Flags), "O_RDONLY"), me.Umask)
|
||||
}
|
||||
|
||||
func (me *GetAttrIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d}", me.Fh_)
|
||||
}
|
||||
|
||||
func (me *MknodIn) string() string {
|
||||
return fmt.Sprintf("{0%o (0%o), %d}", me.Mode, me.Umask, me.Rdev)
|
||||
}
|
||||
|
||||
func (me *ReadIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d off %d sz %d %s L %d %s}",
|
||||
me.Fh, me.Offset, me.Size,
|
||||
FlagString(readFlagNames, int64(me.ReadFlags), ""),
|
||||
me.LockOwner,
|
||||
FlagString(OpenFlagNames, int64(me.Flags), "RDONLY"))
|
||||
}
|
||||
|
||||
func (me *WriteIn) string() string {
|
||||
return fmt.Sprintf("{Fh %d off %d sz %d %s L %d %s}",
|
||||
me.Fh, me.Offset, me.Size,
|
||||
FlagString(writeFlagNames, int64(me.WriteFlags), ""),
|
||||
me.LockOwner,
|
||||
FlagString(OpenFlagNames, int64(me.Flags), "RDONLY"))
|
||||
}
|
||||
75
vendor/github.com/hanwen/go-fuse/fuse/read.go
generated
vendored
Normal file
75
vendor/github.com/hanwen/go-fuse/fuse/read.go
generated
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"io"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// ReadResultData is the read return for returning bytes directly.
|
||||
type readResultData struct {
|
||||
// Raw bytes for the read.
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func (r *readResultData) Size() int {
|
||||
return len(r.Data)
|
||||
}
|
||||
|
||||
func (r *readResultData) Done() {
|
||||
}
|
||||
|
||||
func (r *readResultData) Bytes(buf []byte) ([]byte, Status) {
|
||||
return r.Data, OK
|
||||
}
|
||||
|
||||
func ReadResultData(b []byte) ReadResult {
|
||||
return &readResultData{b}
|
||||
}
|
||||
|
||||
func ReadResultFd(fd uintptr, off int64, sz int) ReadResult {
|
||||
return &readResultFd{fd, off, sz}
|
||||
}
|
||||
|
||||
// ReadResultFd is the read return for zero-copy file data.
|
||||
type readResultFd struct {
|
||||
// Splice from the following file.
|
||||
Fd uintptr
|
||||
|
||||
// Offset within Fd, or -1 to use current offset.
|
||||
Off int64
|
||||
|
||||
// Size of data to be loaded. Actual data available may be
|
||||
// less at the EOF.
|
||||
Sz int
|
||||
}
|
||||
|
||||
// Reads raw bytes from file descriptor if necessary, using the passed
|
||||
// buffer as storage.
|
||||
func (r *readResultFd) Bytes(buf []byte) ([]byte, Status) {
|
||||
sz := r.Sz
|
||||
if len(buf) < sz {
|
||||
sz = len(buf)
|
||||
}
|
||||
|
||||
n, err := syscall.Pread(int(r.Fd), buf[:sz], r.Off)
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if n < 0 {
|
||||
n = 0
|
||||
}
|
||||
|
||||
return buf[:n], ToStatus(err)
|
||||
}
|
||||
|
||||
func (r *readResultFd) Size() int {
|
||||
return r.Sz
|
||||
}
|
||||
|
||||
func (r *readResultFd) Done() {
|
||||
}
|
||||
217
vendor/github.com/hanwen/go-fuse/fuse/request.go
generated
vendored
Normal file
217
vendor/github.com/hanwen/go-fuse/fuse/request.go
generated
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var sizeOfOutHeader = unsafe.Sizeof(OutHeader{})
|
||||
var zeroOutBuf [outputHeaderSize]byte
|
||||
|
||||
type request struct {
|
||||
inputBuf []byte
|
||||
|
||||
// These split up inputBuf.
|
||||
inHeader *InHeader // generic header
|
||||
inData unsafe.Pointer // per op data
|
||||
arg []byte // flat data.
|
||||
|
||||
filenames []string // filename arguments
|
||||
|
||||
// Unstructured data, a pointer to the relevant XxxxOut struct.
|
||||
outData unsafe.Pointer
|
||||
status Status
|
||||
flatData []byte
|
||||
fdData *readResultFd
|
||||
|
||||
// In case of read, keep read result here so we can call
|
||||
// Done() on it.
|
||||
readResult ReadResult
|
||||
|
||||
// Start timestamp for timing info.
|
||||
startTime time.Time
|
||||
|
||||
// All information pertaining to opcode of this request.
|
||||
handler *operationHandler
|
||||
|
||||
// Request storage. For large inputs and outputs, use data
|
||||
// obtained through bufferpool.
|
||||
bufferPoolInputBuf []byte
|
||||
bufferPoolOutputBuf []byte
|
||||
|
||||
// For small pieces of data, we use the following inlines
|
||||
// arrays:
|
||||
//
|
||||
// Output header and structured data.
|
||||
outBuf [outputHeaderSize]byte
|
||||
|
||||
// Input, if small enough to fit here.
|
||||
smallInputBuf [128]byte
|
||||
|
||||
context Context
|
||||
}
|
||||
|
||||
func (r *request) clear() {
|
||||
r.inputBuf = nil
|
||||
r.inHeader = nil
|
||||
r.inData = nil
|
||||
r.arg = nil
|
||||
r.filenames = nil
|
||||
r.outData = nil
|
||||
r.status = OK
|
||||
r.flatData = nil
|
||||
r.fdData = nil
|
||||
r.startTime = time.Time{}
|
||||
r.handler = nil
|
||||
r.readResult = nil
|
||||
}
|
||||
|
||||
func (r *request) InputDebug() string {
|
||||
val := " "
|
||||
if r.handler.DecodeIn != nil {
|
||||
val = fmt.Sprintf(" data: %v ", Print(r.handler.DecodeIn(r.inData)))
|
||||
}
|
||||
|
||||
names := ""
|
||||
if r.filenames != nil {
|
||||
names = fmt.Sprintf("names: %v", r.filenames)
|
||||
}
|
||||
|
||||
if len(r.arg) > 0 {
|
||||
names += fmt.Sprintf(" %d bytes", len(r.arg))
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Dispatch %d: %s, NodeId: %v.%v%v",
|
||||
r.inHeader.Unique, operationName(r.inHeader.Opcode),
|
||||
r.inHeader.NodeId, val, names)
|
||||
}
|
||||
|
||||
func (r *request) OutputDebug() string {
|
||||
var dataStr string
|
||||
if r.handler.DecodeOut != nil && r.outData != nil {
|
||||
dataStr = Print(r.handler.DecodeOut(r.outData))
|
||||
}
|
||||
|
||||
max := 1024
|
||||
if len(dataStr) > max {
|
||||
dataStr = dataStr[:max] + fmt.Sprintf(" ...trimmed")
|
||||
}
|
||||
|
||||
flatStr := ""
|
||||
if r.flatDataSize() > 0 {
|
||||
if r.handler.FileNameOut {
|
||||
s := strings.TrimRight(string(r.flatData), "\x00")
|
||||
flatStr = fmt.Sprintf(" %q", s)
|
||||
} else {
|
||||
spl := ""
|
||||
if r.fdData != nil {
|
||||
spl = " (fd data)"
|
||||
}
|
||||
flatStr = fmt.Sprintf(" %d bytes data%s\n", r.flatDataSize(), spl)
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Serialize %d: %s code: %v value: %v%v",
|
||||
r.inHeader.Unique, operationName(r.inHeader.Opcode), r.status,
|
||||
dataStr, flatStr)
|
||||
}
|
||||
|
||||
// setInput returns true if it takes ownership of the argument, false if not.
|
||||
func (r *request) setInput(input []byte) bool {
|
||||
if len(input) < len(r.smallInputBuf) {
|
||||
copy(r.smallInputBuf[:], input)
|
||||
r.inputBuf = r.smallInputBuf[:len(input)]
|
||||
return false
|
||||
}
|
||||
r.inputBuf = input
|
||||
r.bufferPoolInputBuf = input[:cap(input)]
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *request) parse() {
|
||||
inHSize := int(unsafe.Sizeof(InHeader{}))
|
||||
if len(r.inputBuf) < inHSize {
|
||||
log.Printf("Short read for input header: %v", r.inputBuf)
|
||||
return
|
||||
}
|
||||
|
||||
r.inHeader = (*InHeader)(unsafe.Pointer(&r.inputBuf[0]))
|
||||
r.arg = r.inputBuf[:]
|
||||
|
||||
r.handler = getHandler(r.inHeader.Opcode)
|
||||
if r.handler == nil {
|
||||
log.Printf("Unknown opcode %d", r.inHeader.Opcode)
|
||||
r.status = ENOSYS
|
||||
return
|
||||
}
|
||||
|
||||
if len(r.arg) < int(r.handler.InputSize) {
|
||||
log.Printf("Short read for %v: %v", operationName(r.inHeader.Opcode), r.arg)
|
||||
r.status = EIO
|
||||
return
|
||||
}
|
||||
|
||||
if r.handler.InputSize > 0 {
|
||||
r.inData = unsafe.Pointer(&r.arg[0])
|
||||
r.arg = r.arg[r.handler.InputSize:]
|
||||
} else {
|
||||
r.arg = r.arg[inHSize:]
|
||||
}
|
||||
|
||||
count := r.handler.FileNames
|
||||
if count > 0 {
|
||||
if count == 1 {
|
||||
r.filenames = []string{string(r.arg[:len(r.arg)-1])}
|
||||
} else {
|
||||
names := bytes.SplitN(r.arg[:len(r.arg)-1], []byte{0}, count)
|
||||
r.filenames = make([]string, len(names))
|
||||
for i, n := range names {
|
||||
r.filenames[i] = string(n)
|
||||
}
|
||||
if len(names) != count {
|
||||
log.Println("filename argument mismatch", names, count)
|
||||
r.status = EIO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copy(r.outBuf[:r.handler.OutputSize+sizeOfOutHeader],
|
||||
zeroOutBuf[:r.handler.OutputSize+sizeOfOutHeader])
|
||||
r.outData = unsafe.Pointer(&r.outBuf[sizeOfOutHeader])
|
||||
}
|
||||
|
||||
func (r *request) serializeHeader(dataSize int) (header []byte) {
|
||||
dataLength := r.handler.OutputSize
|
||||
if r.outData == nil || r.status > OK {
|
||||
dataLength = 0
|
||||
}
|
||||
|
||||
sizeOfOutHeader := unsafe.Sizeof(OutHeader{})
|
||||
header = r.outBuf[:sizeOfOutHeader+dataLength]
|
||||
o := (*OutHeader)(unsafe.Pointer(&header[0]))
|
||||
o.Unique = r.inHeader.Unique
|
||||
o.Status = int32(-r.status)
|
||||
o.Length = uint32(
|
||||
int(sizeOfOutHeader) + int(dataLength) + dataSize)
|
||||
|
||||
var asSlice []byte
|
||||
toSlice(&asSlice, r.outData, dataLength)
|
||||
copy(header[sizeOfOutHeader:], asSlice)
|
||||
return header
|
||||
}
|
||||
|
||||
func (r *request) flatDataSize() int {
|
||||
if r.fdData != nil {
|
||||
return r.fdData.Size()
|
||||
}
|
||||
return len(r.flatData)
|
||||
}
|
||||
13
vendor/github.com/hanwen/go-fuse/fuse/request_darwin.go
generated
vendored
Normal file
13
vendor/github.com/hanwen/go-fuse/fuse/request_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
const outputHeaderSize = 200
|
||||
|
||||
const (
|
||||
_FUSE_KERNEL_VERSION = 7
|
||||
_MINIMUM_MINOR_VERSION = 8
|
||||
_OUR_MINOR_VERSION = 8
|
||||
)
|
||||
13
vendor/github.com/hanwen/go-fuse/fuse/request_linux.go
generated
vendored
Normal file
13
vendor/github.com/hanwen/go-fuse/fuse/request_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
const outputHeaderSize = 160
|
||||
|
||||
const (
|
||||
_FUSE_KERNEL_VERSION = 7
|
||||
_MINIMUM_MINOR_VERSION = 12
|
||||
_OUR_MINOR_VERSION = 23
|
||||
)
|
||||
586
vendor/github.com/hanwen/go-fuse/fuse/server.go
generated
vendored
Normal file
586
vendor/github.com/hanwen/go-fuse/fuse/server.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
32
vendor/github.com/hanwen/go-fuse/fuse/server_darwin.go
generated
vendored
Normal file
32
vendor/github.com/hanwen/go-fuse/fuse/server_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (ms *Server) systemWrite(req *request, header []byte) Status {
|
||||
if req.flatDataSize() == 0 {
|
||||
err := handleEINTR(func() error {
|
||||
_, err := syscall.Write(ms.mountFd, header)
|
||||
return err
|
||||
})
|
||||
return ToStatus(err)
|
||||
}
|
||||
|
||||
if req.fdData != nil {
|
||||
sz := req.flatDataSize()
|
||||
buf := ms.allocOut(req, uint32(sz))
|
||||
req.flatData, req.status = req.fdData.Bytes(buf)
|
||||
header = req.serializeHeader(len(req.flatData))
|
||||
}
|
||||
|
||||
_, err := writev(int(ms.mountFd), [][]byte{header, req.flatData})
|
||||
if req.readResult != nil {
|
||||
req.readResult.Done()
|
||||
}
|
||||
return ToStatus(err)
|
||||
}
|
||||
42
vendor/github.com/hanwen/go-fuse/fuse/server_linux.go
generated
vendored
Normal file
42
vendor/github.com/hanwen/go-fuse/fuse/server_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"log"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (ms *Server) systemWrite(req *request, header []byte) Status {
|
||||
if req.flatDataSize() == 0 {
|
||||
err := handleEINTR(func() error {
|
||||
_, err := syscall.Write(ms.mountFd, header)
|
||||
return err
|
||||
})
|
||||
return ToStatus(err)
|
||||
}
|
||||
|
||||
if req.fdData != nil {
|
||||
if ms.canSplice {
|
||||
err := ms.trySplice(header, req, req.fdData)
|
||||
if err == nil {
|
||||
req.readResult.Done()
|
||||
return OK
|
||||
}
|
||||
log.Println("trySplice:", err)
|
||||
}
|
||||
|
||||
sz := req.flatDataSize()
|
||||
buf := ms.allocOut(req, uint32(sz))
|
||||
req.flatData, req.status = req.fdData.Bytes(buf)
|
||||
header = req.serializeHeader(len(req.flatData))
|
||||
}
|
||||
|
||||
_, err := writev(ms.mountFd, [][]byte{header, req.flatData})
|
||||
if req.readResult != nil {
|
||||
req.readResult.Done()
|
||||
}
|
||||
return ToStatus(err)
|
||||
}
|
||||
17
vendor/github.com/hanwen/go-fuse/fuse/splice_darwin.go
generated
vendored
Normal file
17
vendor/github.com/hanwen/go-fuse/fuse/splice_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (s *Server) setSplice() {
|
||||
s.canSplice = false
|
||||
}
|
||||
|
||||
func (ms *Server) trySplice(header []byte, req *request, fdData *readResultFd) error {
|
||||
return fmt.Errorf("unimplemented")
|
||||
}
|
||||
97
vendor/github.com/hanwen/go-fuse/fuse/splice_linux.go
generated
vendored
Normal file
97
vendor/github.com/hanwen/go-fuse/fuse/splice_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/hanwen/go-fuse/splice"
|
||||
)
|
||||
|
||||
func (s *Server) setSplice() {
|
||||
s.canSplice = splice.Resizable()
|
||||
}
|
||||
|
||||
// trySplice: Zero-copy read from fdData.Fd into /dev/fuse
|
||||
//
|
||||
// This is a four-step process:
|
||||
//
|
||||
// 1) Splice data form fdData.Fd into the "pair1" pipe buffer --> pair1: [payload]
|
||||
// Now we know the actual payload length and can
|
||||
// construct the reply header
|
||||
// 2) Write header into the "pair2" pipe buffer --> pair2: [header]
|
||||
// 4) Splice data from "pair1" into "pair2" --> pair2: [header][payload]
|
||||
// 3) Splice the data from "pair2" into /dev/fuse
|
||||
//
|
||||
// This dance is neccessary because header and payload cannot be split across
|
||||
// two splices and we cannot seek in a pipe buffer.
|
||||
func (ms *Server) trySplice(header []byte, req *request, fdData *readResultFd) error {
|
||||
var err error
|
||||
|
||||
// Get a pair of connected pipes
|
||||
pair1, err := splice.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer splice.Done(pair1)
|
||||
|
||||
// Grow buffer pipe to requested size + one extra page
|
||||
// Without the extra page the kernel will block once the pipe is almost full
|
||||
pair1Sz := fdData.Size() + os.Getpagesize()
|
||||
if err := pair1.Grow(pair1Sz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read data from file
|
||||
payloadLen, err := pair1.LoadFromAt(fdData.Fd, fdData.Size(), fdData.Off)
|
||||
|
||||
if err != nil {
|
||||
// TODO - extract the data from splice.
|
||||
return err
|
||||
}
|
||||
|
||||
// Get another pair of connected pipes
|
||||
pair2, err := splice.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer splice.Done(pair2)
|
||||
|
||||
// Grow pipe to header + actually read size + one extra page
|
||||
// Without the extra page the kernel will block once the pipe is almost full
|
||||
header = req.serializeHeader(payloadLen)
|
||||
total := len(header) + payloadLen
|
||||
pair2Sz := total + os.Getpagesize()
|
||||
if err := pair2.Grow(pair2Sz); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write header into pair2
|
||||
n, err := pair2.Write(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != len(header) {
|
||||
return fmt.Errorf("Short write into splice: wrote %d, want %d", n, len(header))
|
||||
}
|
||||
|
||||
// Write data into pair2
|
||||
n, err = pair2.LoadFrom(pair1.ReadFd(), payloadLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n != payloadLen {
|
||||
return fmt.Errorf("Short splice: wrote %d, want %d", n, payloadLen)
|
||||
}
|
||||
|
||||
// Write header + data to /dev/fuse
|
||||
_, err = pair2.WriteTo(uintptr(ms.mountFd), total)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
139
vendor/github.com/hanwen/go-fuse/fuse/syscall_darwin.go
generated
vendored
Normal file
139
vendor/github.com/hanwen/go-fuse/fuse/syscall_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TODO - move these into Go's syscall package.
|
||||
|
||||
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) {
|
||||
n1, _, e1 := syscall.Syscall(
|
||||
syscall.SYS_WRITEV,
|
||||
uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
|
||||
n = int(n1)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func writev(fd int, packet [][]byte) (n int, err error) {
|
||||
iovecs := make([]syscall.Iovec, 0, len(packet))
|
||||
|
||||
for _, v := range packet {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
vec := syscall.Iovec{
|
||||
Base: &v[0],
|
||||
}
|
||||
vec.SetLen(len(v))
|
||||
iovecs = append(iovecs, vec)
|
||||
}
|
||||
|
||||
sysErr := handleEINTR(func() error {
|
||||
var err error
|
||||
n, err = sys_writev(fd, &iovecs[0], len(iovecs))
|
||||
return err
|
||||
})
|
||||
if sysErr != nil {
|
||||
err = os.NewSyscallError("writev", sysErr)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func getxattr(path string, attr string, dest []byte) (sz int, errno int) {
|
||||
pathBs := syscall.StringBytePtr(path)
|
||||
attrBs := syscall.StringBytePtr(attr)
|
||||
size, _, errNo := syscall.Syscall6(
|
||||
syscall.SYS_GETXATTR,
|
||||
uintptr(unsafe.Pointer(pathBs)),
|
||||
uintptr(unsafe.Pointer(attrBs)),
|
||||
uintptr(unsafe.Pointer(&dest[0])),
|
||||
uintptr(len(dest)),
|
||||
0, 0)
|
||||
return int(size), int(errNo)
|
||||
}
|
||||
|
||||
func GetXAttr(path string, attr string, dest []byte) (value []byte, errno int) {
|
||||
sz, errno := getxattr(path, attr, dest)
|
||||
|
||||
for sz > cap(dest) && errno == 0 {
|
||||
dest = make([]byte, sz)
|
||||
sz, errno = getxattr(path, attr, dest)
|
||||
}
|
||||
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
return dest[:sz], errno
|
||||
}
|
||||
|
||||
func listxattr(path string, dest []byte) (sz int, errno int) {
|
||||
pathbs := syscall.StringBytePtr(path)
|
||||
var destPointer unsafe.Pointer
|
||||
if len(dest) > 0 {
|
||||
destPointer = unsafe.Pointer(&dest[0])
|
||||
}
|
||||
size, _, errNo := syscall.Syscall(
|
||||
syscall.SYS_LISTXATTR,
|
||||
uintptr(unsafe.Pointer(pathbs)),
|
||||
uintptr(destPointer),
|
||||
uintptr(len(dest)))
|
||||
|
||||
return int(size), int(errNo)
|
||||
}
|
||||
|
||||
func ListXAttr(path string) (attributes []string, errno int) {
|
||||
dest := make([]byte, 0)
|
||||
sz, errno := listxattr(path, dest)
|
||||
if errno != 0 {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
for sz > cap(dest) && errno == 0 {
|
||||
dest = make([]byte, sz)
|
||||
sz, errno = listxattr(path, dest)
|
||||
}
|
||||
|
||||
// -1 to drop the final empty slice.
|
||||
dest = dest[:sz-1]
|
||||
attributesBytes := bytes.Split(dest, []byte{0})
|
||||
attributes = make([]string, len(attributesBytes))
|
||||
for i, v := range attributesBytes {
|
||||
attributes[i] = string(v)
|
||||
}
|
||||
return attributes, errno
|
||||
}
|
||||
|
||||
func Setxattr(path string, attr string, data []byte, flags int) (errno int) {
|
||||
pathbs := syscall.StringBytePtr(path)
|
||||
attrbs := syscall.StringBytePtr(attr)
|
||||
_, _, errNo := syscall.Syscall6(
|
||||
syscall.SYS_SETXATTR,
|
||||
uintptr(unsafe.Pointer(pathbs)),
|
||||
uintptr(unsafe.Pointer(attrbs)),
|
||||
uintptr(unsafe.Pointer(&data[0])),
|
||||
uintptr(len(data)),
|
||||
uintptr(flags), 0)
|
||||
|
||||
return int(errNo)
|
||||
}
|
||||
|
||||
func Removexattr(path string, attr string) (errno int) {
|
||||
pathbs := syscall.StringBytePtr(path)
|
||||
attrbs := syscall.StringBytePtr(attr)
|
||||
_, _, errNo := syscall.Syscall(
|
||||
syscall.SYS_REMOVEXATTR,
|
||||
uintptr(unsafe.Pointer(pathbs)),
|
||||
uintptr(unsafe.Pointer(attrbs)), 0)
|
||||
return int(errNo)
|
||||
}
|
||||
49
vendor/github.com/hanwen/go-fuse/fuse/syscall_linux.go
generated
vendored
Normal file
49
vendor/github.com/hanwen/go-fuse/fuse/syscall_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// TODO - move these into Go's syscall package.
|
||||
|
||||
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) {
|
||||
n1, _, e1 := syscall.Syscall(
|
||||
syscall.SYS_WRITEV,
|
||||
uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
|
||||
n = int(n1)
|
||||
if e1 != 0 {
|
||||
err = syscall.Errno(e1)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func writev(fd int, packet [][]byte) (n int, err error) {
|
||||
iovecs := make([]syscall.Iovec, 0, len(packet))
|
||||
|
||||
for _, v := range packet {
|
||||
if len(v) == 0 {
|
||||
continue
|
||||
}
|
||||
vec := syscall.Iovec{
|
||||
Base: &v[0],
|
||||
}
|
||||
vec.SetLen(len(v))
|
||||
iovecs = append(iovecs, vec)
|
||||
}
|
||||
|
||||
sysErr := handleEINTR(func() error {
|
||||
var err error
|
||||
n, err = sys_writev(fd, &iovecs[0], len(iovecs))
|
||||
return err
|
||||
})
|
||||
if sysErr != nil {
|
||||
err = os.NewSyscallError("writev", sysErr)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
9
vendor/github.com/hanwen/go-fuse/fuse/typeprint.go
generated
vendored
Normal file
9
vendor/github.com/hanwen/go-fuse/fuse/typeprint.go
generated
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
func (a *Attr) String() string {
|
||||
return Print((*Attr)(a))
|
||||
}
|
||||
470
vendor/github.com/hanwen/go-fuse/fuse/types.go
generated
vendored
Normal file
470
vendor/github.com/hanwen/go-fuse/fuse/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,470 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
_DEFAULT_BACKGROUND_TASKS = 12
|
||||
)
|
||||
|
||||
// Status is the errno number that a FUSE call returns to the kernel.
|
||||
type Status int32
|
||||
|
||||
const (
|
||||
OK = Status(0)
|
||||
|
||||
// EACCESS Permission denied
|
||||
EACCES = Status(syscall.EACCES)
|
||||
|
||||
// EBUSY Device or resource busy
|
||||
EBUSY = Status(syscall.EBUSY)
|
||||
|
||||
// EAGAIN Resource temporarily unavailable
|
||||
EAGAIN = Status(syscall.EAGAIN)
|
||||
|
||||
// EINVAL Invalid argument
|
||||
EINVAL = Status(syscall.EINVAL)
|
||||
|
||||
// EIO I/O error
|
||||
EIO = Status(syscall.EIO)
|
||||
|
||||
// ENOENT No such file or directory
|
||||
ENOENT = Status(syscall.ENOENT)
|
||||
|
||||
// ENOSYS Function not implemented
|
||||
ENOSYS = Status(syscall.ENOSYS)
|
||||
|
||||
// ENODATA No data available
|
||||
ENODATA = Status(syscall.ENODATA)
|
||||
|
||||
// ENOTDIR Not a directory
|
||||
ENOTDIR = Status(syscall.ENOTDIR)
|
||||
|
||||
// EPERM Operation not permitted
|
||||
EPERM = Status(syscall.EPERM)
|
||||
|
||||
// ERANGE Math result not representable
|
||||
ERANGE = Status(syscall.ERANGE)
|
||||
|
||||
// EXDEV Cross-device link
|
||||
EXDEV = Status(syscall.EXDEV)
|
||||
|
||||
// EBADF Bad file number
|
||||
EBADF = Status(syscall.EBADF)
|
||||
|
||||
// ENODEV No such device
|
||||
ENODEV = Status(syscall.ENODEV)
|
||||
|
||||
// EROFS Read-only file system
|
||||
EROFS = Status(syscall.EROFS)
|
||||
)
|
||||
|
||||
type ForgetIn struct {
|
||||
InHeader
|
||||
|
||||
Nlookup uint64
|
||||
}
|
||||
|
||||
// batch forget is handled internally.
|
||||
type _ForgetOne struct {
|
||||
NodeId uint64
|
||||
Nlookup uint64
|
||||
}
|
||||
|
||||
// batch forget is handled internally.
|
||||
type _BatchForgetIn struct {
|
||||
InHeader
|
||||
Count uint32
|
||||
Dummy uint32
|
||||
}
|
||||
|
||||
type MkdirIn struct {
|
||||
InHeader
|
||||
Mode uint32
|
||||
Umask uint32
|
||||
}
|
||||
|
||||
type RenameIn struct {
|
||||
InHeader
|
||||
Newdir uint64
|
||||
}
|
||||
|
||||
type Rename2In struct {
|
||||
InHeader
|
||||
Newdir uint64
|
||||
Flags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type LinkIn struct {
|
||||
InHeader
|
||||
Oldnodeid uint64
|
||||
}
|
||||
|
||||
type Owner struct {
|
||||
Uid uint32
|
||||
Gid uint32
|
||||
}
|
||||
|
||||
const ( // SetAttrIn.Valid
|
||||
FATTR_MODE = (1 << 0)
|
||||
FATTR_UID = (1 << 1)
|
||||
FATTR_GID = (1 << 2)
|
||||
FATTR_SIZE = (1 << 3)
|
||||
FATTR_ATIME = (1 << 4)
|
||||
FATTR_MTIME = (1 << 5)
|
||||
FATTR_FH = (1 << 6)
|
||||
FATTR_ATIME_NOW = (1 << 7)
|
||||
FATTR_MTIME_NOW = (1 << 8)
|
||||
FATTR_LOCKOWNER = (1 << 9)
|
||||
FATTR_CTIME = (1 << 10)
|
||||
)
|
||||
|
||||
type SetAttrInCommon struct {
|
||||
InHeader
|
||||
|
||||
Valid uint32
|
||||
Padding uint32
|
||||
Fh uint64
|
||||
Size uint64
|
||||
LockOwner uint64
|
||||
Atime uint64
|
||||
Mtime uint64
|
||||
Ctime uint64
|
||||
Atimensec uint32
|
||||
Mtimensec uint32
|
||||
Ctimensec uint32
|
||||
Mode uint32
|
||||
Unused4 uint32
|
||||
Owner
|
||||
Unused5 uint32
|
||||
}
|
||||
|
||||
const RELEASE_FLUSH = (1 << 0)
|
||||
|
||||
type ReleaseIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Flags uint32
|
||||
ReleaseFlags uint32
|
||||
LockOwner uint64
|
||||
}
|
||||
|
||||
type OpenIn struct {
|
||||
InHeader
|
||||
Flags uint32
|
||||
Mode uint32
|
||||
}
|
||||
|
||||
const (
|
||||
// OpenOut.Flags
|
||||
FOPEN_DIRECT_IO = (1 << 0)
|
||||
FOPEN_KEEP_CACHE = (1 << 1)
|
||||
FOPEN_NONSEEKABLE = (1 << 2)
|
||||
)
|
||||
|
||||
type OpenOut struct {
|
||||
Fh uint64
|
||||
OpenFlags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
// To be set in InitIn/InitOut.Flags.
|
||||
const (
|
||||
CAP_ASYNC_READ = (1 << 0)
|
||||
CAP_POSIX_LOCKS = (1 << 1)
|
||||
CAP_FILE_OPS = (1 << 2)
|
||||
CAP_ATOMIC_O_TRUNC = (1 << 3)
|
||||
CAP_EXPORT_SUPPORT = (1 << 4)
|
||||
CAP_BIG_WRITES = (1 << 5)
|
||||
CAP_DONT_MASK = (1 << 6)
|
||||
CAP_SPLICE_WRITE = (1 << 7)
|
||||
CAP_SPLICE_MOVE = (1 << 8)
|
||||
CAP_SPLICE_READ = (1 << 9)
|
||||
CAP_FLOCK_LOCKS = (1 << 10)
|
||||
CAP_IOCTL_DIR = (1 << 11)
|
||||
CAP_AUTO_INVAL_DATA = (1 << 12)
|
||||
CAP_READDIRPLUS = (1 << 13)
|
||||
CAP_READDIRPLUS_AUTO = (1 << 14)
|
||||
CAP_ASYNC_DIO = (1 << 15)
|
||||
CAP_WRITEBACK_CACHE = (1 << 16)
|
||||
CAP_NO_OPEN_SUPPORT = (1 << 17)
|
||||
)
|
||||
|
||||
type InitIn struct {
|
||||
InHeader
|
||||
|
||||
Major uint32
|
||||
Minor uint32
|
||||
MaxReadAhead uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type InitOut struct {
|
||||
Major uint32
|
||||
Minor uint32
|
||||
MaxReadAhead uint32
|
||||
Flags uint32
|
||||
MaxBackground uint16
|
||||
CongestionThreshold uint16
|
||||
MaxWrite uint32
|
||||
TimeGran uint32
|
||||
Unused [9]uint32
|
||||
}
|
||||
|
||||
type _CuseInitIn struct {
|
||||
InHeader
|
||||
Major uint32
|
||||
Minor uint32
|
||||
Unused uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type _CuseInitOut struct {
|
||||
Major uint32
|
||||
Minor uint32
|
||||
Unused uint32
|
||||
Flags uint32
|
||||
MaxRead uint32
|
||||
MaxWrite uint32
|
||||
DevMajor uint32
|
||||
DevMinor uint32
|
||||
Spare [10]uint32
|
||||
}
|
||||
|
||||
type InterruptIn struct {
|
||||
InHeader
|
||||
Unique uint64
|
||||
}
|
||||
|
||||
type _BmapIn struct {
|
||||
InHeader
|
||||
Block uint64
|
||||
Blocksize uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type _BmapOut struct {
|
||||
Block uint64
|
||||
}
|
||||
|
||||
const (
|
||||
FUSE_IOCTL_COMPAT = (1 << 0)
|
||||
FUSE_IOCTL_UNRESTRICTED = (1 << 1)
|
||||
FUSE_IOCTL_RETRY = (1 << 2)
|
||||
)
|
||||
|
||||
type _IoctlIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Flags uint32
|
||||
Cmd uint32
|
||||
Arg uint64
|
||||
InSize uint32
|
||||
OutSize uint32
|
||||
}
|
||||
|
||||
type _IoctlOut struct {
|
||||
Result int32
|
||||
Flags uint32
|
||||
InIovs uint32
|
||||
OutIovs uint32
|
||||
}
|
||||
|
||||
type _PollIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Kh uint64
|
||||
Flags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type _PollOut struct {
|
||||
Revents uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type _NotifyPollWakeupOut struct {
|
||||
Kh uint64
|
||||
}
|
||||
|
||||
type WriteOut struct {
|
||||
Size uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type GetXAttrOut struct {
|
||||
Size uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type _FileLock struct {
|
||||
Start uint64
|
||||
End uint64
|
||||
Typ uint32
|
||||
Pid uint32
|
||||
}
|
||||
|
||||
type _LkIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Owner uint64
|
||||
Lk _FileLock
|
||||
LkFlags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type _LkOut struct {
|
||||
Lk _FileLock
|
||||
}
|
||||
|
||||
// For AccessIn.Mask.
|
||||
const (
|
||||
X_OK = 1
|
||||
W_OK = 2
|
||||
R_OK = 4
|
||||
F_OK = 0
|
||||
)
|
||||
|
||||
type AccessIn struct {
|
||||
InHeader
|
||||
Mask uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type FsyncIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
FsyncFlags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type OutHeader struct {
|
||||
Length uint32
|
||||
Status int32
|
||||
Unique uint64
|
||||
}
|
||||
|
||||
type NotifyInvalInodeOut struct {
|
||||
Ino uint64
|
||||
Off int64
|
||||
Length int64
|
||||
}
|
||||
|
||||
type NotifyInvalEntryOut struct {
|
||||
Parent uint64
|
||||
NameLen uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type NotifyInvalDeleteOut struct {
|
||||
Parent uint64
|
||||
Child uint64
|
||||
NameLen uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
const (
|
||||
// NOTIFY_POLL = -1
|
||||
NOTIFY_INVAL_INODE = -2
|
||||
NOTIFY_INVAL_ENTRY = -3
|
||||
// NOTIFY_STORE = -4
|
||||
// NOTIFY_RETRIEVE = -5
|
||||
NOTIFY_INVAL_DELETE = -6
|
||||
|
||||
// NOTIFY_CODE_MAX = -6
|
||||
)
|
||||
|
||||
type FlushIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Unused uint32
|
||||
Padding uint32
|
||||
LockOwner uint64
|
||||
}
|
||||
|
||||
type EntryOut struct {
|
||||
NodeId uint64
|
||||
Generation uint64
|
||||
EntryValid uint64
|
||||
AttrValid uint64
|
||||
EntryValidNsec uint32
|
||||
AttrValidNsec uint32
|
||||
Attr
|
||||
}
|
||||
|
||||
type AttrOut struct {
|
||||
AttrValid uint64
|
||||
AttrValidNsec uint32
|
||||
Dummy uint32
|
||||
Attr
|
||||
}
|
||||
|
||||
type CreateOut struct {
|
||||
EntryOut
|
||||
OpenOut
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Owner
|
||||
Pid uint32
|
||||
}
|
||||
|
||||
type InHeader struct {
|
||||
Length uint32
|
||||
Opcode int32
|
||||
Unique uint64
|
||||
NodeId uint64
|
||||
Context
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type StatfsOut struct {
|
||||
Blocks uint64
|
||||
Bfree uint64
|
||||
Bavail uint64
|
||||
Files uint64
|
||||
Ffree uint64
|
||||
Bsize uint32
|
||||
NameLen uint32
|
||||
Frsize uint32
|
||||
Padding uint32
|
||||
Spare [6]uint32
|
||||
}
|
||||
|
||||
// _Dirent is what we send to the kernel, but we offer DirEntry and
|
||||
// DirEntryList to the user.
|
||||
type _Dirent struct {
|
||||
Ino uint64
|
||||
Off uint64
|
||||
NameLen uint32
|
||||
Typ uint32
|
||||
}
|
||||
|
||||
const (
|
||||
READ_LOCKOWNER = (1 << 1)
|
||||
)
|
||||
|
||||
const (
|
||||
WRITE_CACHE = (1 << 0)
|
||||
WRITE_LOCKOWNER = (1 << 1)
|
||||
)
|
||||
|
||||
type FallocateIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Offset uint64
|
||||
Length uint64
|
||||
Mode uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type FlockIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
}
|
||||
153
vendor/github.com/hanwen/go-fuse/fuse/types_darwin.go
generated
vendored
Normal file
153
vendor/github.com/hanwen/go-fuse/fuse/types_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
ENOATTR = Status(syscall.ENOATTR) // ENOATTR is not defined for all GOOS.
|
||||
)
|
||||
|
||||
type Attr struct {
|
||||
Ino uint64
|
||||
Size uint64
|
||||
Blocks uint64
|
||||
Atime uint64
|
||||
Mtime uint64
|
||||
Ctime uint64
|
||||
Crtime_ uint64 // OS X
|
||||
Atimensec uint32
|
||||
Mtimensec uint32
|
||||
Ctimensec uint32
|
||||
Crtimensec_ uint32 // OS X
|
||||
Mode uint32
|
||||
Nlink uint32
|
||||
Owner
|
||||
Rdev uint32
|
||||
Flags_ uint32 // OS X
|
||||
}
|
||||
|
||||
const (
|
||||
FATTR_CRTIME = (1 << 28)
|
||||
FATTR_CHGTIME = (1 << 29)
|
||||
FATTR_BKUPTIME = (1 << 30)
|
||||
FATTR_FLAGS = (1 << 31)
|
||||
)
|
||||
|
||||
type SetAttrIn struct {
|
||||
SetAttrInCommon
|
||||
|
||||
// OS X only
|
||||
Bkuptime_ uint64
|
||||
Chgtime_ uint64
|
||||
Crtime uint64
|
||||
BkuptimeNsec uint32
|
||||
ChgtimeNsec uint32
|
||||
CrtimeNsec uint32
|
||||
Flags_ uint32 // see chflags(2)
|
||||
}
|
||||
|
||||
const (
|
||||
FOPEN_PURGE_ATTR = (1 << 30)
|
||||
FOPEN_PURGE_UBC = (1 << 31)
|
||||
)
|
||||
|
||||
// compat with linux.
|
||||
const (
|
||||
// Mask for GetAttrIn.Flags. If set, GetAttrIn has a file handle set.
|
||||
FUSE_GETATTR_FH = (1 << 0)
|
||||
)
|
||||
|
||||
type GetAttrIn struct {
|
||||
InHeader
|
||||
}
|
||||
|
||||
func (g *GetAttrIn) Flags() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (g *GetAttrIn) Fh() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uses OpenIn struct for create.
|
||||
type CreateIn struct {
|
||||
InHeader
|
||||
|
||||
Flags uint32
|
||||
Mode uint32
|
||||
}
|
||||
|
||||
type MknodIn struct {
|
||||
InHeader
|
||||
|
||||
Mode uint32
|
||||
Rdev uint32
|
||||
}
|
||||
|
||||
type ReadIn struct {
|
||||
InHeader
|
||||
|
||||
Fh uint64
|
||||
Offset uint64
|
||||
Size uint32
|
||||
ReadFlags uint32
|
||||
}
|
||||
|
||||
type WriteIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Offset uint64
|
||||
Size uint32
|
||||
WriteFlags uint32
|
||||
}
|
||||
|
||||
type SetXAttrIn struct {
|
||||
InHeader
|
||||
Size uint32
|
||||
Flags uint32
|
||||
Position uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type GetXAttrIn struct {
|
||||
InHeader
|
||||
Size uint32
|
||||
Padding uint32
|
||||
Position uint32
|
||||
Padding2 uint32
|
||||
}
|
||||
|
||||
const (
|
||||
CAP_CASE_INSENSITIVE = (1 << 29)
|
||||
CAP_VOL_RENAME = (1 << 30)
|
||||
CAP_XTIMES = (1 << 31)
|
||||
)
|
||||
|
||||
type GetxtimesOut struct {
|
||||
Bkuptime uint64
|
||||
Crtime uint64
|
||||
Bkuptimensec uint32
|
||||
Crtimensec uint32
|
||||
}
|
||||
|
||||
type ExchangeIn struct {
|
||||
InHeader
|
||||
Olddir uint64
|
||||
Newdir uint64
|
||||
Options uint64
|
||||
}
|
||||
|
||||
func (s *StatfsOut) FromStatfsT(statfs *syscall.Statfs_t) {
|
||||
s.Blocks = statfs.Blocks
|
||||
s.Bfree = statfs.Bfree
|
||||
s.Bavail = statfs.Bavail
|
||||
s.Files = statfs.Files
|
||||
s.Ffree = statfs.Ffree
|
||||
s.Bsize = uint32(statfs.Iosize) // Iosize translates to Bsize: the optimal transfer size.
|
||||
s.Frsize = s.Bsize // Bsize translates to Frsize: the minimum transfer size.
|
||||
}
|
||||
121
vendor/github.com/hanwen/go-fuse/fuse/types_linux.go
generated
vendored
Normal file
121
vendor/github.com/hanwen/go-fuse/fuse/types_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
const (
|
||||
ENOATTR = Status(syscall.ENODATA) // On Linux, ENOATTR is an alias for ENODATA.
|
||||
)
|
||||
|
||||
type Attr struct {
|
||||
Ino uint64
|
||||
Size uint64
|
||||
Blocks uint64
|
||||
Atime uint64
|
||||
Mtime uint64
|
||||
Ctime uint64
|
||||
Atimensec uint32
|
||||
Mtimensec uint32
|
||||
Ctimensec uint32
|
||||
Mode uint32
|
||||
Nlink uint32
|
||||
Owner
|
||||
Rdev uint32
|
||||
Blksize uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type SetAttrIn struct {
|
||||
SetAttrInCommon
|
||||
}
|
||||
|
||||
const (
|
||||
// Mask for GetAttrIn.Flags. If set, GetAttrIn has a file handle set.
|
||||
FUSE_GETATTR_FH = (1 << 0)
|
||||
)
|
||||
|
||||
type GetAttrIn struct {
|
||||
InHeader
|
||||
|
||||
Flags_ uint32
|
||||
Dummy uint32
|
||||
Fh_ uint64
|
||||
}
|
||||
|
||||
// Flags accesses the flags. This is a method, because OSXFuse does not
|
||||
// have GetAttrIn flags.
|
||||
func (g *GetAttrIn) Flags() uint32 {
|
||||
return g.Flags_
|
||||
}
|
||||
|
||||
// Fh accesses the file handle. This is a method, because OSXFuse does not
|
||||
// have GetAttrIn flags.
|
||||
func (g *GetAttrIn) Fh() uint64 {
|
||||
return g.Fh_
|
||||
}
|
||||
|
||||
type CreateIn struct {
|
||||
InHeader
|
||||
Flags uint32
|
||||
Mode uint32
|
||||
Umask uint32
|
||||
Pading uint32
|
||||
}
|
||||
|
||||
type MknodIn struct {
|
||||
InHeader
|
||||
Mode uint32
|
||||
Rdev uint32
|
||||
Umask uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type ReadIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Offset uint64
|
||||
Size uint32
|
||||
ReadFlags uint32
|
||||
LockOwner uint64
|
||||
Flags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type WriteIn struct {
|
||||
InHeader
|
||||
Fh uint64
|
||||
Offset uint64
|
||||
Size uint32
|
||||
WriteFlags uint32
|
||||
LockOwner uint64
|
||||
Flags uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
type SetXAttrIn struct {
|
||||
InHeader
|
||||
Size uint32
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
type GetXAttrIn struct {
|
||||
InHeader
|
||||
Size uint32
|
||||
Padding uint32
|
||||
}
|
||||
|
||||
func (s *StatfsOut) FromStatfsT(statfs *syscall.Statfs_t) {
|
||||
s.Blocks = statfs.Blocks
|
||||
s.Bsize = uint32(statfs.Bsize)
|
||||
s.Bfree = statfs.Bfree
|
||||
s.Bavail = statfs.Bavail
|
||||
s.Files = statfs.Files
|
||||
s.Ffree = statfs.Ffree
|
||||
s.Frsize = uint32(statfs.Frsize)
|
||||
s.NameLen = uint32(statfs.Namelen)
|
||||
}
|
||||
333
vendor/github.com/hanwen/go-fuse/fuse/upgrade.go
generated
vendored
Normal file
333
vendor/github.com/hanwen/go-fuse/fuse/upgrade.go
generated
vendored
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fuse
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// NewRawFileSystem adds the methods missing for implementing a
|
||||
// RawFileSystem to any object.
|
||||
func NewRawFileSystem(fs interface{}) RawFileSystem {
|
||||
return &wrappingFS{fs}
|
||||
}
|
||||
|
||||
type wrappingFS struct {
|
||||
fs interface{}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Init(srv *Server) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Init(*Server)
|
||||
}); ok {
|
||||
s.Init(srv)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) String() string {
|
||||
return fmt.Sprintf("%v", fs.fs)
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) SetDebug(dbg bool) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
SetDebug(bool)
|
||||
}); ok {
|
||||
s.SetDebug(dbg)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) StatFs(header *InHeader, out *StatfsOut) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
StatFs(header *InHeader, out *StatfsOut) Status
|
||||
}); ok {
|
||||
return s.StatFs(header, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Lookup(header *InHeader, name string, out *EntryOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Lookup(header *InHeader, name string, out *EntryOut) (code Status)
|
||||
}); ok {
|
||||
return s.Lookup(header, name, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Forget(nodeID, nlookup uint64) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Forget(nodeID, nlookup uint64)
|
||||
}); ok {
|
||||
s.Forget(nodeID, nlookup)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) GetAttr(input *GetAttrIn, out *AttrOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
GetAttr(input *GetAttrIn, out *AttrOut) (code Status)
|
||||
}); ok {
|
||||
return s.GetAttr(input, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Open(input *OpenIn, out *OpenOut) (status Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Open(input *OpenIn, out *OpenOut) (status Status)
|
||||
}); ok {
|
||||
return s.Open(input, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) SetAttr(input *SetAttrIn, out *AttrOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
SetAttr(input *SetAttrIn, out *AttrOut) (code Status)
|
||||
}); ok {
|
||||
return s.SetAttr(input, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Readlink(header *InHeader) (out []byte, code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Readlink(header *InHeader) (out []byte, code Status)
|
||||
}); ok {
|
||||
return s.Readlink(header)
|
||||
}
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Mknod(input *MknodIn, name string, out *EntryOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Mknod(input *MknodIn, name string, out *EntryOut) (code Status)
|
||||
}); ok {
|
||||
return s.Mknod(input, name, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Mkdir(input *MkdirIn, name string, out *EntryOut) (code Status)
|
||||
}); ok {
|
||||
return s.Mkdir(input, name, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Unlink(header *InHeader, name string) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Unlink(header *InHeader, name string) (code Status)
|
||||
}); ok {
|
||||
return s.Unlink(header, name)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Rmdir(header *InHeader, name string) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Rmdir(header *InHeader, name string) (code Status)
|
||||
}); ok {
|
||||
return s.Rmdir(header, name)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Symlink(header *InHeader, pointedTo string, linkName string, out *EntryOut) (code Status)
|
||||
}); ok {
|
||||
return s.Symlink(header, pointedTo, linkName, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Rename(input *RenameIn, oldName string, newName string) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Rename(input *RenameIn, oldName string, newName string) (code Status)
|
||||
}); ok {
|
||||
return s.Rename(input, oldName, newName)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Link(input *LinkIn, name string, out *EntryOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Link(input *LinkIn, name string, out *EntryOut) (code Status)
|
||||
}); ok {
|
||||
return s.Link(input, name, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) GetXAttrSize(header *InHeader, attr string) (size int, code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
GetXAttrSize(header *InHeader, attr string) (size int, code Status)
|
||||
}); ok {
|
||||
return s.GetXAttrSize(header, attr)
|
||||
}
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) GetXAttrData(header *InHeader, attr string) (data []byte, code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
GetXAttrData(header *InHeader, attr string) (data []byte, code Status)
|
||||
}); ok {
|
||||
return s.GetXAttrData(header, attr)
|
||||
}
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) SetXAttr(input *SetXAttrIn, attr string, data []byte) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
SetXAttr(input *SetXAttrIn, attr string, data []byte) Status
|
||||
}); ok {
|
||||
return s.SetXAttr(input, attr, data)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) ListXAttr(header *InHeader) (data []byte, code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
ListXAttr(header *InHeader) (data []byte, code Status)
|
||||
}); ok {
|
||||
return s.ListXAttr(header)
|
||||
}
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) RemoveXAttr(header *InHeader, attr string) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
RemoveXAttr(header *InHeader, attr string) Status
|
||||
}); ok {
|
||||
return s.RemoveXAttr(header, attr)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Access(input *AccessIn) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Access(input *AccessIn) (code Status)
|
||||
}); ok {
|
||||
return s.Access(input)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Create(input *CreateIn, name string, out *CreateOut) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Create(input *CreateIn, name string, out *CreateOut) (code Status)
|
||||
}); ok {
|
||||
return s.Create(input, name, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) OpenDir(input *OpenIn, out *OpenOut) (status Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
OpenDir(input *OpenIn, out *OpenOut) (status Status)
|
||||
}); ok {
|
||||
return s.OpenDir(input, out)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Read(input *ReadIn, buf []byte) (ReadResult, Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Read(input *ReadIn, buf []byte) (ReadResult, Status)
|
||||
}); ok {
|
||||
return s.Read(input, buf)
|
||||
}
|
||||
return nil, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Flock(input *FlockIn, flags int) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Flock(input *FlockIn, flags int) Status
|
||||
}); ok {
|
||||
return s.Flock(input, flags)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Release(input *ReleaseIn) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Release(input *ReleaseIn)
|
||||
}); ok {
|
||||
s.Release(input)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Write(input *WriteIn, data []byte) (written uint32, code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Write(input *WriteIn, data []byte) (written uint32, code Status)
|
||||
}); ok {
|
||||
return s.Write(input, data)
|
||||
}
|
||||
return 0, ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Flush(input *FlushIn) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Flush(input *FlushIn) Status
|
||||
}); ok {
|
||||
return s.Flush(input)
|
||||
}
|
||||
return OK
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Fsync(input *FsyncIn) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Fsync(input *FsyncIn) (code Status)
|
||||
}); ok {
|
||||
return s.Fsync(input)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) ReadDir(input *ReadIn, l *DirEntryList) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
ReadDir(input *ReadIn, l *DirEntryList) Status
|
||||
}); ok {
|
||||
return s.ReadDir(input, l)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) ReadDirPlus(input *ReadIn, l *DirEntryList) Status {
|
||||
if s, ok := fs.fs.(interface {
|
||||
ReadDirPlus(input *ReadIn, l *DirEntryList) Status
|
||||
}); ok {
|
||||
return s.ReadDirPlus(input, l)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) ReleaseDir(input *ReleaseIn) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
ReleaseDir(input *ReleaseIn)
|
||||
}); ok {
|
||||
s.ReleaseDir(input)
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) FsyncDir(input *FsyncIn) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
FsyncDir(input *FsyncIn) (code Status)
|
||||
}); ok {
|
||||
return s.FsyncDir(input)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
|
||||
func (fs *wrappingFS) Fallocate(in *FallocateIn) (code Status) {
|
||||
if s, ok := fs.fs.(interface {
|
||||
Fallocate(in *FallocateIn) (code Status)
|
||||
}); ok {
|
||||
return s.Fallocate(in)
|
||||
}
|
||||
return ENOSYS
|
||||
}
|
||||
70
vendor/github.com/hanwen/go-fuse/splice/copy.go
generated
vendored
Normal file
70
vendor/github.com/hanwen/go-fuse/splice/copy.go
generated
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
func SpliceCopy(dst *os.File, src *os.File, p *Pair) (int64, error) {
|
||||
total := int64(0)
|
||||
|
||||
for {
|
||||
n, err := p.LoadFrom(src.Fd(), p.size)
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
if n == 0 {
|
||||
break
|
||||
}
|
||||
m, err := p.WriteTo(dst.Fd(), n)
|
||||
total += int64(m)
|
||||
if err != nil {
|
||||
return total, err
|
||||
}
|
||||
if m < n {
|
||||
return total, err
|
||||
}
|
||||
if int(n) < p.size {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// Argument ordering follows io.Copy.
|
||||
func CopyFile(dstName string, srcName string, mode int) error {
|
||||
src, err := os.Open(srcName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.FileMode(mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
return CopyFds(dst, src)
|
||||
}
|
||||
|
||||
func CopyFds(dst *os.File, src *os.File) (err error) {
|
||||
p, err := splicePool.get()
|
||||
if p != nil {
|
||||
p.Grow(256 * 1024)
|
||||
_, err := SpliceCopy(dst, src, p)
|
||||
splicePool.done(p)
|
||||
return err
|
||||
} else {
|
||||
_, err = io.Copy(dst, src)
|
||||
}
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
68
vendor/github.com/hanwen/go-fuse/splice/pair.go
generated
vendored
Normal file
68
vendor/github.com/hanwen/go-fuse/splice/pair.go
generated
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type Pair struct {
|
||||
r, w *os.File
|
||||
size int
|
||||
}
|
||||
|
||||
func (p *Pair) MaxGrow() {
|
||||
for p.Grow(2*p.size) == nil {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Pair) Grow(n int) error {
|
||||
if n <= p.size {
|
||||
return nil
|
||||
}
|
||||
if !resizable {
|
||||
return fmt.Errorf("splice: want %d bytes, but not resizable", n)
|
||||
}
|
||||
if n > maxPipeSize {
|
||||
return fmt.Errorf("splice: want %d bytes, max pipe size %d", n, maxPipeSize)
|
||||
}
|
||||
|
||||
newsize, errNo := fcntl(p.r.Fd(), F_SETPIPE_SZ, n)
|
||||
if errNo != 0 {
|
||||
return fmt.Errorf("splice: fcntl returned %v", errNo)
|
||||
}
|
||||
p.size = newsize
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pair) Cap() int {
|
||||
return p.size
|
||||
}
|
||||
|
||||
func (p *Pair) Close() error {
|
||||
err1 := p.r.Close()
|
||||
err2 := p.w.Close()
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
return err2
|
||||
}
|
||||
|
||||
func (p *Pair) Read(d []byte) (n int, err error) {
|
||||
return p.r.Read(d)
|
||||
}
|
||||
|
||||
func (p *Pair) ReadFd() uintptr {
|
||||
return p.r.Fd()
|
||||
}
|
||||
|
||||
func (p *Pair) WriteFd() uintptr {
|
||||
return p.w.Fd()
|
||||
}
|
||||
|
||||
func (p *Pair) Write(d []byte) (n int, err error) {
|
||||
return p.w.Write(d)
|
||||
}
|
||||
22
vendor/github.com/hanwen/go-fuse/splice/pair_darwin.go
generated
vendored
Normal file
22
vendor/github.com/hanwen/go-fuse/splice/pair_darwin.go
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
import ()
|
||||
|
||||
func (p *Pair) LoadFromAt(fd uintptr, sz int, off int64) (int, error) {
|
||||
panic("not implemented")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *Pair) LoadFrom(fd uintptr, sz int) (int, error) {
|
||||
panic("not implemented")
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (p *Pair) WriteTo(fd uintptr, n int) (int, error) {
|
||||
panic("not implemented")
|
||||
return 0, nil
|
||||
}
|
||||
37
vendor/github.com/hanwen/go-fuse/splice/pair_linux.go
generated
vendored
Normal file
37
vendor/github.com/hanwen/go-fuse/splice/pair_linux.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func (p *Pair) LoadFromAt(fd uintptr, sz int, off int64) (int, error) {
|
||||
n, err := syscall.Splice(int(fd), &off, int(p.w.Fd()), nil, sz, 0)
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func (p *Pair) LoadFrom(fd uintptr, sz int) (int, error) {
|
||||
if sz > p.size {
|
||||
return 0, fmt.Errorf("LoadFrom: not enough space %d, %d",
|
||||
sz, p.size)
|
||||
}
|
||||
|
||||
n, err := syscall.Splice(int(fd), nil, int(p.w.Fd()), nil, sz, 0)
|
||||
if err != nil {
|
||||
err = os.NewSyscallError("Splice load from", err)
|
||||
}
|
||||
return int(n), err
|
||||
}
|
||||
|
||||
func (p *Pair) WriteTo(fd uintptr, n int) (int, error) {
|
||||
m, err := syscall.Splice(int(p.r.Fd()), nil, int(fd), nil, int(n), 0)
|
||||
if err != nil {
|
||||
err = os.NewSyscallError("Splice write", err)
|
||||
}
|
||||
return int(m), err
|
||||
}
|
||||
119
vendor/github.com/hanwen/go-fuse/splice/pool.go
generated
vendored
Normal file
119
vendor/github.com/hanwen/go-fuse/splice/pool.go
generated
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var splicePool *pairPool
|
||||
|
||||
type pairPool struct {
|
||||
sync.Mutex
|
||||
unused []*Pair
|
||||
usedCount int
|
||||
}
|
||||
|
||||
func ClearSplicePool() {
|
||||
splicePool.clear()
|
||||
}
|
||||
|
||||
func Get() (*Pair, error) {
|
||||
return splicePool.get()
|
||||
}
|
||||
|
||||
func Total() int {
|
||||
return splicePool.total()
|
||||
}
|
||||
|
||||
func Used() int {
|
||||
return splicePool.used()
|
||||
}
|
||||
|
||||
// Return pipe pair to pool
|
||||
func Done(p *Pair) {
|
||||
splicePool.done(p)
|
||||
}
|
||||
|
||||
// Closes and discards pipe pair.
|
||||
func Drop(p *Pair) {
|
||||
splicePool.drop(p)
|
||||
}
|
||||
|
||||
func newSplicePairPool() *pairPool {
|
||||
return &pairPool{}
|
||||
}
|
||||
|
||||
func (me *pairPool) clear() {
|
||||
me.Lock()
|
||||
for _, p := range me.unused {
|
||||
p.Close()
|
||||
}
|
||||
me.unused = me.unused[:0]
|
||||
me.Unlock()
|
||||
}
|
||||
|
||||
func (me *pairPool) used() (n int) {
|
||||
me.Lock()
|
||||
n = me.usedCount
|
||||
me.Unlock()
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
func (me *pairPool) total() int {
|
||||
me.Lock()
|
||||
n := me.usedCount + len(me.unused)
|
||||
me.Unlock()
|
||||
return n
|
||||
}
|
||||
|
||||
func (me *pairPool) drop(p *Pair) {
|
||||
p.Close()
|
||||
me.Lock()
|
||||
me.usedCount--
|
||||
me.Unlock()
|
||||
}
|
||||
|
||||
func (me *pairPool) get() (p *Pair, err error) {
|
||||
me.Lock()
|
||||
defer me.Unlock()
|
||||
|
||||
me.usedCount++
|
||||
l := len(me.unused)
|
||||
if l > 0 {
|
||||
p := me.unused[l-1]
|
||||
me.unused = me.unused[:l-1]
|
||||
return p, nil
|
||||
}
|
||||
|
||||
return newSplicePair()
|
||||
}
|
||||
|
||||
var discardBuffer [32 * 1024]byte
|
||||
|
||||
func DiscardAll(r io.Reader) {
|
||||
buf := discardBuffer[:]
|
||||
for {
|
||||
n, _ := r.Read(buf)
|
||||
if n < len(buf) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (me *pairPool) done(p *Pair) {
|
||||
DiscardAll(p.r)
|
||||
|
||||
me.Lock()
|
||||
me.usedCount--
|
||||
me.unused = append(me.unused, p)
|
||||
me.Unlock()
|
||||
}
|
||||
|
||||
func init() {
|
||||
splicePool = newSplicePairPool()
|
||||
}
|
||||
90
vendor/github.com/hanwen/go-fuse/splice/splice.go
generated
vendored
Normal file
90
vendor/github.com/hanwen/go-fuse/splice/splice.go
generated
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2016 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package splice
|
||||
|
||||
// Routines for efficient file to file copying.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var maxPipeSize int
|
||||
var resizable bool
|
||||
|
||||
func Resizable() bool {
|
||||
return resizable
|
||||
}
|
||||
|
||||
func MaxPipeSize() int {
|
||||
return maxPipeSize
|
||||
}
|
||||
|
||||
// From manpage on ubuntu Lucid:
|
||||
//
|
||||
// Since Linux 2.6.11, the pipe capacity is 65536 bytes.
|
||||
const DefaultPipeSize = 16 * 4096
|
||||
|
||||
func init() {
|
||||
content, err := ioutil.ReadFile("/proc/sys/fs/pipe-max-size")
|
||||
if err != nil {
|
||||
maxPipeSize = DefaultPipeSize
|
||||
} else {
|
||||
fmt.Sscan(string(content), &maxPipeSize)
|
||||
}
|
||||
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
log.Panicf("cannot create pipe: %v", err)
|
||||
}
|
||||
sz, errNo := fcntl(r.Fd(), F_GETPIPE_SZ, 0)
|
||||
resizable = (errNo == 0)
|
||||
_, errNo = fcntl(r.Fd(), F_SETPIPE_SZ, 2*sz)
|
||||
resizable = resizable && (errNo == 0)
|
||||
r.Close()
|
||||
w.Close()
|
||||
}
|
||||
|
||||
// copy & paste from syscall.
|
||||
func fcntl(fd uintptr, cmd int, arg int) (val int, errno syscall.Errno) {
|
||||
r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, fd, uintptr(cmd), uintptr(arg))
|
||||
val = int(r0)
|
||||
errno = syscall.Errno(e1)
|
||||
return
|
||||
}
|
||||
|
||||
const F_SETPIPE_SZ = 1031
|
||||
const F_GETPIPE_SZ = 1032
|
||||
|
||||
func newSplicePair() (p *Pair, err error) {
|
||||
p = &Pair{}
|
||||
p.r, p.w, err = os.Pipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errNo := syscall.Errno(0)
|
||||
for _, f := range []*os.File{p.r, p.w} {
|
||||
_, errNo = fcntl(f.Fd(), syscall.F_SETFL, syscall.O_NONBLOCK)
|
||||
if errNo != 0 {
|
||||
p.Close()
|
||||
return nil, os.NewSyscallError("fcntl setfl", errNo)
|
||||
}
|
||||
}
|
||||
|
||||
p.size, errNo = fcntl(p.r.Fd(), F_GETPIPE_SZ, 0)
|
||||
if errNo == syscall.EINVAL {
|
||||
p.size = DefaultPipeSize
|
||||
return p, nil
|
||||
}
|
||||
if errNo != 0 {
|
||||
p.Close()
|
||||
return nil, os.NewSyscallError("fcntl getsize", errNo)
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue