Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
153eda7c
Commit
153eda7c
authored
Oct 25, 2020
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
go mod vendor
parent
e3e61d67
Changes
65
Show whitespace changes
Inline
Side-by-side
Showing
65 changed files
with
4 additions
and
8838 deletions
+4
-8838
wcfs/go.mod
wcfs/go.mod
+3
-3
wcfs/vendor/github.com/hanwen/go-fuse/v2/AUTHORS
wcfs/vendor/github.com/hanwen/go-fuse/v2/AUTHORS
+0
-20
wcfs/vendor/github.com/hanwen/go-fuse/v2/LICENSE
wcfs/vendor/github.com/hanwen/go-fuse/v2/LICENSE
+0
-30
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/.gitignore
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/.gitignore
+0
-1
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go
+0
-283
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr.go
+0
-79
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_darwin.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_darwin.go
+0
-26
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_linux.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_linux.go
+0
-27
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/bufferpool.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/bufferpool.go
+0
-69
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants.go
+0
-37
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants_freebsd.go
...or/github.com/hanwen/go-fuse/v2/fuse/constants_freebsd.go
+0
-9
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants_linux.go
...ndor/github.com/hanwen/go-fuse/v2/fuse/constants_linux.go
+0
-12
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/context.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/context.go
+0
-61
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/defaultraw.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/defaultraw.go
+0
-168
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/direntry.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/direntry.go
+0
-141
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/misc.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/misc.go
+0
-100
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go
+0
-97
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_linux.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_linux.go
+0
-202
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/api.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/api.go
+0
-215
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultfile.go
...r/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultfile.go
+0
-86
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultnode.go
...r/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultnode.go
+0
-184
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/dir.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/dir.go
+0
-113
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files.go
+0
-304
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files_darwin.go
.../github.com/hanwen/go-fuse/v2/fuse/nodefs/files_darwin.go
+0
-97
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files_linux.go
...r/github.com/hanwen/go-fuse/v2/fuse/nodefs/files_linux.go
+0
-33
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsconnector.go
...r/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsconnector.go
+0
-488
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsmount.go
...endor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsmount.go
+0
-186
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsops.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsops.go
+0
-505
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fuse.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fuse.go
+0
-29
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/handle.go
...vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/handle.go
+0
-151
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/inode.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/inode.go
+0
-295
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/lockingfile.go
...r/github.com/hanwen/go-fuse/v2/fuse/nodefs/lockingfile.go
+0
-121
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/memnode.go
...endor/github.com/hanwen/go-fuse/v2/fuse/nodefs/memnode.go
+0
-252
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/syscall_linux.go
...github.com/hanwen/go-fuse/v2/fuse/nodefs/syscall_linux.go
+0
-20
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/opcode.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/opcode.go
+0
-808
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go
+0
-42
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_darwin.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_darwin.go
+0
-49
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_linux.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_linux.go
+0
-25
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print.go
+0
-305
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print_darwin.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/print_darwin.go
+0
-54
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print_linux.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print_linux.go
+0
-61
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/read.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/read.go
+0
-75
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request.go
+0
-265
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request_darwin.go
...endor/github.com/hanwen/go-fuse/v2/fuse/request_darwin.go
+0
-13
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request_linux.go
...vendor/github.com/hanwen/go-fuse/v2/fuse/request_linux.go
+0
-13
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go
+0
-856
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server_darwin.go
...vendor/github.com/hanwen/go-fuse/v2/fuse/server_darwin.go
+0
-32
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server_linux.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/server_linux.go
+0
-42
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/splice_darwin.go
...vendor/github.com/hanwen/go-fuse/v2/fuse/splice_darwin.go
+0
-17
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/splice_linux.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/splice_linux.go
+0
-97
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/syscall_darwin.go
...endor/github.com/hanwen/go-fuse/v2/fuse/syscall_darwin.go
+0
-139
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/syscall_linux.go
...vendor/github.com/hanwen/go-fuse/v2/fuse/syscall_linux.go
+0
-49
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/typeprint.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/typeprint.go
+0
-9
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types.go
+0
-676
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types_darwin.go
.../vendor/github.com/hanwen/go-fuse/v2/fuse/types_darwin.go
+0
-166
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types_linux.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types_linux.go
+0
-134
wcfs/vendor/github.com/hanwen/go-fuse/v2/internal/utimens/utimens_darwin.go
....com/hanwen/go-fuse/v2/internal/utimens/utimens_darwin.go
+0
-40
wcfs/vendor/github.com/hanwen/go-fuse/v2/internal/utimens/utimens_linux.go
...b.com/hanwen/go-fuse/v2/internal/utimens/utimens_linux.go
+0
-7
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/copy.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/copy.go
+0
-70
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair.go
+0
-68
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair_darwin.go
...vendor/github.com/hanwen/go-fuse/v2/splice/pair_darwin.go
+0
-22
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair_linux.go
.../vendor/github.com/hanwen/go-fuse/v2/splice/pair_linux.go
+0
-54
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pool.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pool.go
+0
-105
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/splice.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/splice.go
+0
-97
wcfs/vendor/modules.txt
wcfs/vendor/modules.txt
+1
-4
No files found.
wcfs/go.mod
View file @
153eda7c
...
...
@@ -3,11 +3,11 @@ module lab.nexedi.com/nexedi/wendelin.core/wcfs
go 1.14
require (
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/hanwen/go-fuse/v2 v2.0.3 // replaced to -> kirr/go-fuse@y/nodefs-cancel
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
// indirect
github.com/hanwen/go-fuse/v2 v2.0.3 //
indirect;
replaced to -> kirr/go-fuse@y/nodefs-cancel
github.com/johncgriffin/overflow v0.0.0-20170615021017-4d914c927216
github.com/kisielk/og-rek v1.0.1-0.20180928202415-8b25c4cefd6c
github.com/pkg/errors v0.9.1
github.com/pkg/errors v0.9.1
// indirect
github.com/stretchr/testify v1.6.1
lab.nexedi.com/kirr/go123 v0.0.0-20200916121347-316617668e12
lab.nexedi.com/kirr/neo/go v0.0.0-20201012044742-28494187df87
...
...
wcfs/vendor/github.com/hanwen/go-fuse/v2/AUTHORS
deleted
100644 → 0
View file @
e3e61d67
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>
Kaoet Ibe <kaoet.ibe@outlook.com>
Kirill Smelkov <kirr@nexedi.com>
Logan Hanks <logan@bitcasa.com>
Maria Shaldibina <mshaldibina@pivotal.io>
Nick Cooper <gh@smoogle.org>
Patrick Crosby <pcrosby@gmail.com>
Paul Jolly <paul@myitcv.org.uk>
Paul Warren <paul.warren@emc.com>
Shayan Pooya <shayan@arista.com>
Valient Gough <vgough@pobox.com>
Yongwoo Park <nnnlife@gmail.com>
wcfs/vendor/github.com/hanwen/go-fuse/v2/LICENSE
deleted
100644 → 0
View file @
e3e61d67
// 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.
//
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/.gitignore
deleted
100644 → 0
View file @
e3e61d67
version.gen.go
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/api.go
deleted
100644 → 0
View file @
e3e61d67
// 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 provides APIs to implement filesystems in
// userspace in terms of raw FUSE protocol.
//
// A filesystem is implemented by implementing its server that provides a
// RawFileSystem interface. Typically the server embeds
// NewDefaultRawFileSystem() and implements only subset of filesystem methods:
//
// type MyFS struct {
// fuse.RawFileSystem
// ...
// }
//
// func NewMyFS() *MyFS {
// return &MyFS{
// RawFileSystem: fuse.NewDefaultRawFileSystem(),
// ...
// }
// }
//
// // Mkdir implements "mkdir" request handler.
// //
// // For other requests - not explicitly implemented by MyFS - ENOSYS
// // will be typically returned to client.
// func (fs *MyFS) Mkdir(...) {
// ...
// }
//
// Then the filesystem can be mounted and served to a client (typically OS
// kernel) by creating Server:
//
// fs := NewMyFS() // implements RawFileSystem
// fssrv, err := fuse.NewServer(fs, mountpoint, &fuse.MountOptions{...})
// if err != nil {
// ...
// }
//
// and letting the server do its work:
//
// // either synchronously - .Serve() blocks until the filesystem is unmounted.
// fssrv.Serve()
//
// // or in the background - .Serve() is spawned in another goroutine, but
// // before interacting with fssrv from current context we have to wait
// // until the filesystem mounting is complete.
// go fssrv.Serve()
// err = fssrv.WaitMount()
// if err != nil {
// ...
// }
//
// The server will serve clients by dispatching their requests to the
// filesystem implementation and conveying responses back. For example "mkdir"
// FUSE request dispatches to call
//
// fs.Mkdir(*MkdirIn, ..., *EntryOut)
//
// "stat" to call
//
// fs.GetAttr(*GetAttrIn, *AttrOut)
//
// etc. Please refer to RawFileSystem documentation for details.
//
// Typically, each call of the API happens in its own
// goroutine, so take care to make the file system thread-safe.
//
//
// Higher level interfaces
//
// As said above this packages provides way to implement filesystems in terms of
// raw FUSE protocol. Additionally packages nodefs and pathfs provide ways to
// implement filesystem at higher levels:
//
// Package github.com/hanwen/go-fuse/fuse/nodefs provides way to implement
// filesystems in terms of inodes. This resembles kernel's idea of what a
// filesystem looks like.
//
// Package github.com/hanwen/go-fuse/fuse/pathfs provides way to implement
// filesystems in terms of path names. Working with path names is somewhat
// easier compared to inodes, however renames can be racy. Do not use pathfs if
// you care about correctness.
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 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
// If set, ask kernel to forward file locks to FUSE. If using,
// you must implement the GetLk/SetLk/SetLkw methods.
EnableLocks
bool
// If set, ask kernel not to do automatic data cache invalidation.
// The filesystem is fully responsible for invalidating data cache.
ExplicitDataCacheControl
bool
// If set, fuse will first attempt to use syscall.Mount instead of
// fusermount to mount the filesystem. This will not update /etc/mtab
// but might be needed if fusermount is not available.
DirectMount
bool
// Options passed to syscall.Mount, the default value used by fusermount
// is syscall.MS_NOSUID|syscall.MS_NODEV
DirectMountFlags
uintptr
}
// 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 nodefs.Node or pathfs.FileSystem interfaces; the
// details of getting interactions with open files, renames, and threading
// right etc. are somewhat tricky and not very interesting.
//
// Each FUSE request results in a corresponding method called by Server.
// Several calls may be made simultaneously, because the server typically calls
// each method in separate goroutine.
//
// A null implementation is provided by NewDefaultRawFileSystem.
//
// After a successful FUSE API call returns, you may not read input or
// write output data: for performance reasons, memory is reused for
// following requests, and reading/writing the request data will lead
// to race conditions. If you spawn a background routine from a FUSE
// API call, any incoming request data it wants to reference should be
// copied over.
//
// If a FUSE API call is canceled (which is signaled by closing the
// `cancel` channel), the API call should return EINTR. In this case,
// the outstanding request data is not reused, so the API call may
// return EINTR without ensuring that child contexts have successfully
// completed.
type
RawFileSystem
interface
{
String
()
string
// If called, provide debug output through the log package.
SetDebug
(
debug
bool
)
// Lookup is called by the kernel when the VFS wants to know
// about a file inside a directory. Many lookup calls can
// occur in parallel, but only one call happens for each (dir,
// name) pair.
Lookup
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
,
out
*
EntryOut
)
(
status
Status
)
// Forget is called when the kernel discards entries from its
// dentry cache. This happens on unmount, and when the kernel
// is short on memory. Since it is not guaranteed to occur at
// any moment, and since there is no return value, Forget
// should not do I/O, as there is no channel to report back
// I/O errors.
Forget
(
nodeid
,
nlookup
uint64
)
// Attributes.
GetAttr
(
cancel
<-
chan
struct
{},
input
*
GetAttrIn
,
out
*
AttrOut
)
(
code
Status
)
SetAttr
(
cancel
<-
chan
struct
{},
input
*
SetAttrIn
,
out
*
AttrOut
)
(
code
Status
)
// Modifying structure.
Mknod
(
cancel
<-
chan
struct
{},
input
*
MknodIn
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
Mkdir
(
cancel
<-
chan
struct
{},
input
*
MkdirIn
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
Unlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
)
(
code
Status
)
Rmdir
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
)
(
code
Status
)
Rename
(
cancel
<-
chan
struct
{},
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
Link
(
cancel
<-
chan
struct
{},
input
*
LinkIn
,
filename
string
,
out
*
EntryOut
)
(
code
Status
)
Symlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
pointedTo
string
,
linkName
string
,
out
*
EntryOut
)
(
code
Status
)
Readlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
Access
(
cancel
<-
chan
struct
{},
input
*
AccessIn
)
(
code
Status
)
// Extended attributes.
// GetXAttr reads an extended attribute, and should return the
// number of bytes. If the buffer is too small, return ERANGE,
// with the required buffer size.
GetXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
attr
string
,
dest
[]
byte
)
(
sz
uint32
,
code
Status
)
// ListXAttr lists extended attributes as '\0' delimited byte
// slice, and return the number of bytes. If the buffer is too
// small, return ERANGE, with the required buffer size.
ListXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
dest
[]
byte
)
(
uint32
,
Status
)
// SetAttr writes an extended attribute.
SetXAttr
(
cancel
<-
chan
struct
{},
input
*
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
// RemoveXAttr removes an extended attribute.
RemoveXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
attr
string
)
(
code
Status
)
// File handling.
Create
(
cancel
<-
chan
struct
{},
input
*
CreateIn
,
name
string
,
out
*
CreateOut
)
(
code
Status
)
Open
(
cancel
<-
chan
struct
{},
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
Read
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
buf
[]
byte
)
(
ReadResult
,
Status
)
Lseek
(
cancel
<-
chan
struct
{},
in
*
LseekIn
,
out
*
LseekOut
)
Status
// File locking
GetLk
(
cancel
<-
chan
struct
{},
input
*
LkIn
,
out
*
LkOut
)
(
code
Status
)
SetLk
(
cancel
<-
chan
struct
{},
input
*
LkIn
)
(
code
Status
)
SetLkw
(
cancel
<-
chan
struct
{},
input
*
LkIn
)
(
code
Status
)
Release
(
cancel
<-
chan
struct
{},
input
*
ReleaseIn
)
Write
(
cancel
<-
chan
struct
{},
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
CopyFileRange
(
cancel
<-
chan
struct
{},
input
*
CopyFileRangeIn
)
(
written
uint32
,
code
Status
)
Flush
(
cancel
<-
chan
struct
{},
input
*
FlushIn
)
Status
Fsync
(
cancel
<-
chan
struct
{},
input
*
FsyncIn
)
(
code
Status
)
Fallocate
(
cancel
<-
chan
struct
{},
input
*
FallocateIn
)
(
code
Status
)
// Directory handling
OpenDir
(
cancel
<-
chan
struct
{},
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
ReadDir
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
out
*
DirEntryList
)
Status
ReadDirPlus
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
out
*
DirEntryList
)
Status
ReleaseDir
(
input
*
ReleaseIn
)
FsyncDir
(
cancel
<-
chan
struct
{},
input
*
FsyncIn
)
(
code
Status
)
StatFs
(
cancel
<-
chan
struct
{},
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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr.go
deleted
100644 → 0
View file @
e3e61d67
// 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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/attr_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/bufferpool.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
)
// bufferPool implements explicit memory management. It is used for
// minimizing the GC overhead of communicating with the kernel.
type
bufferPool
struct
{
lock
sync
.
Mutex
// For each page size multiple a list of slice pointers.
buffersBySize
[]
*
sync
.
Pool
}
var
pageSize
=
os
.
Getpagesize
()
func
(
p
*
bufferPool
)
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
}
// AllocBuffer creates a buffer of at least the given size. After use,
// it should be deallocated with FreeBuffer().
func
(
p
*
bufferPool
)
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
]
}
// FreeBuffer takes back a buffer if it was allocated through
// AllocBuffer. It is not an error to call FreeBuffer() on a slice
// obtained elsewhere.
func
(
p
*
bufferPool
)
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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
logicalBlockSize
=
512
)
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants_freebsd.go
deleted
100644 → 0
View file @
e3e61d67
// 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
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/constants_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/context.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
"context"
"time"
)
// Context passes along cancelation signal and request data (PID, GID,
// UID). The name of this class predates the standard "context"
// package from Go, but it does implement the context.Context
// interface.
//
// When a FUSE request is canceled, the API routine should respond by
// returning the EINTR status code.
type
Context
struct
{
Caller
Cancel
<-
chan
struct
{}
}
func
(
c
*
Context
)
Deadline
()
(
time
.
Time
,
bool
)
{
return
time
.
Time
{},
false
}
func
(
c
*
Context
)
Done
()
<-
chan
struct
{}
{
return
c
.
Cancel
}
func
(
c
*
Context
)
Err
()
error
{
select
{
case
<-
c
.
Cancel
:
return
context
.
Canceled
default
:
return
nil
}
}
type
callerKeyType
struct
{}
var
callerKey
callerKeyType
func
FromContext
(
ctx
context
.
Context
)
(
*
Caller
,
bool
)
{
v
,
ok
:=
ctx
.
Value
(
callerKey
)
.
(
*
Caller
)
return
v
,
ok
}
func
NewContext
(
ctx
context
.
Context
,
caller
*
Caller
)
context
.
Context
{
return
context
.
WithValue
(
ctx
,
callerKey
,
caller
)
}
func
(
c
*
Context
)
Value
(
key
interface
{})
interface
{}
{
if
key
==
callerKey
{
return
&
c
.
Caller
}
return
nil
}
var
_
=
context
.
Context
((
*
Context
)(
nil
))
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/defaultraw.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
out
*
StatfsOut
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Lookup
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Forget
(
nodeID
,
nlookup
uint64
)
{
}
func
(
fs
*
defaultRawFileSystem
)
GetAttr
(
cancel
<-
chan
struct
{},
input
*
GetAttrIn
,
out
*
AttrOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Open
(
cancel
<-
chan
struct
{},
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
{
return
OK
}
func
(
fs
*
defaultRawFileSystem
)
SetAttr
(
cancel
<-
chan
struct
{},
input
*
SetAttrIn
,
out
*
AttrOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Readlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
)
(
out
[]
byte
,
code
Status
)
{
return
nil
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Mknod
(
cancel
<-
chan
struct
{},
input
*
MknodIn
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Mkdir
(
cancel
<-
chan
struct
{},
input
*
MkdirIn
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Unlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Rmdir
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
name
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Symlink
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
pointedTo
string
,
linkName
string
,
out
*
EntryOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Rename
(
cancel
<-
chan
struct
{},
input
*
RenameIn
,
oldName
string
,
newName
string
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Link
(
cancel
<-
chan
struct
{},
input
*
LinkIn
,
name
string
,
out
*
EntryOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
GetXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
attr
string
,
dest
[]
byte
)
(
size
uint32
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
SetXAttr
(
cancel
<-
chan
struct
{},
input
*
SetXAttrIn
,
attr
string
,
data
[]
byte
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
ListXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
dest
[]
byte
)
(
n
uint32
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
RemoveXAttr
(
cancel
<-
chan
struct
{},
header
*
InHeader
,
attr
string
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Access
(
cancel
<-
chan
struct
{},
input
*
AccessIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Create
(
cancel
<-
chan
struct
{},
input
*
CreateIn
,
name
string
,
out
*
CreateOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
OpenDir
(
cancel
<-
chan
struct
{},
input
*
OpenIn
,
out
*
OpenOut
)
(
status
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Read
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
buf
[]
byte
)
(
ReadResult
,
Status
)
{
return
nil
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
GetLk
(
cancel
<-
chan
struct
{},
in
*
LkIn
,
out
*
LkOut
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
SetLk
(
cancel
<-
chan
struct
{},
in
*
LkIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
SetLkw
(
cancel
<-
chan
struct
{},
in
*
LkIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Release
(
cancel
<-
chan
struct
{},
input
*
ReleaseIn
)
{
}
func
(
fs
*
defaultRawFileSystem
)
Write
(
cancel
<-
chan
struct
{},
input
*
WriteIn
,
data
[]
byte
)
(
written
uint32
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Flush
(
cancel
<-
chan
struct
{},
input
*
FlushIn
)
Status
{
return
OK
}
func
(
fs
*
defaultRawFileSystem
)
Fsync
(
cancel
<-
chan
struct
{},
input
*
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
ReadDir
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
l
*
DirEntryList
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
ReadDirPlus
(
cancel
<-
chan
struct
{},
input
*
ReadIn
,
l
*
DirEntryList
)
Status
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
ReleaseDir
(
input
*
ReleaseIn
)
{
}
func
(
fs
*
defaultRawFileSystem
)
FsyncDir
(
cancel
<-
chan
struct
{},
input
*
FsyncIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Fallocate
(
cancel
<-
chan
struct
{},
in
*
FallocateIn
)
(
code
Status
)
{
return
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
CopyFileRange
(
cancel
<-
chan
struct
{},
input
*
CopyFileRangeIn
)
(
written
uint32
,
code
Status
)
{
return
0
,
ENOSYS
}
func
(
fs
*
defaultRawFileSystem
)
Lseek
(
cancel
<-
chan
struct
{},
in
*
LseekIn
,
out
*
LseekOut
)
Status
{
return
ENOSYS
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/direntry.go
deleted
100644 → 0
View file @
e3e61d67
// 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
// Ino is the inode number.
Ino
uint64
}
func
(
d
DirEntry
)
String
()
string
{
return
fmt
.
Sprintf
(
"%o: %q ino=%d"
,
d
.
Mode
,
d
.
Name
,
d
.
Ino
)
}
// DirEntryList holds the return value for READDIR and READDIRPLUS
// opcodes.
type
DirEntryList
struct
{
buf
[]
byte
// capacity of the underlying buffer
size
int
// offset is the requested location in the directory. go-fuse
// currently counts in number of directory entries, but this is an
// implementation detail and may change in the future.
// If `offset` and `fs.fileEntry.dirOffset` disagree, then a
// directory seek has taken place.
offset
uint64
// pointer to the last serialized _Dirent. Used by FixMode().
lastDirent
*
_Dirent
}
// 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
{
return
l
.
Add
(
0
,
e
.
Name
,
e
.
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
{
if
inode
==
0
{
inode
=
FUSE_UNKNOWN_INO
}
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
.
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
=
modeToType
(
mode
)
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
}
// AddDirLookupEntry is used for ReadDirPlus. If reserves and zeroizes space
// for an EntryOut struct and serializes a DirEntry.
// On success, it returns pointers to both structs.
// If not enough space was left, it returns two nil pointers.
//
// The resulting READDIRPLUS output buffer looks like this in memory:
// 1) EntryOut{}
// 2) _Dirent{}
// 3) Name (null-terminated)
// 4) Padding to align to 8 bytes
// [repeat]
func
(
l
*
DirEntryList
)
AddDirLookupEntry
(
e
DirEntry
)
*
EntryOut
{
const
entryOutSize
=
int
(
unsafe
.
Sizeof
(
EntryOut
{}))
oldLen
:=
len
(
l
.
buf
)
ok
:=
l
.
Add
(
entryOutSize
,
e
.
Name
,
e
.
Ino
,
e
.
Mode
)
if
!
ok
{
return
nil
}
l
.
lastDirent
=
(
*
_Dirent
)(
unsafe
.
Pointer
(
&
l
.
buf
[
oldLen
+
entryOutSize
]))
entryOut
:=
(
*
EntryOut
)(
unsafe
.
Pointer
(
&
l
.
buf
[
oldLen
]))
*
entryOut
=
EntryOut
{}
// zeroize
return
entryOut
}
// modeToType converts a file *mode* (as used in syscall.Stat_t.Mode)
// to a file *type* (as used in _Dirent.Typ).
// Equivalent to IFTODT() in libc (see man 5 dirent).
func
modeToType
(
mode
uint32
)
uint32
{
return
(
mode
&
0170000
)
>>
12
}
// FixMode overrides the file mode of the last direntry that was added. This can
// be needed when a directory changes while READDIRPLUS is running.
// Only the file type bits of mode are considered, the rest is masked out.
func
(
l
*
DirEntryList
)
FixMode
(
mode
uint32
)
{
l
.
lastDirent
.
Typ
=
modeToType
(
mode
)
}
func
(
l
*
DirEntryList
)
bytes
()
[]
byte
{
return
l
.
buf
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/misc.go
deleted
100644 → 0
View file @
e3e61d67
// 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_STORE_CACHE"
,
"NOTIFY_RETRIEVE_CACHE"
,
"NOTIFY_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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
{
bin
:=
oldLoadBin
if
_
,
err
:=
os
.
Stat
(
newLoadBin
);
err
==
nil
{
bin
=
newLoadBin
}
cmd
:=
exec
.
Command
(
bin
)
if
err
:=
cmd
.
Run
();
err
!=
nil
{
return
nil
,
err
}
fs
,
err
=
filepath
.
Glob
(
"/dev/osxfuse*"
)
if
err
!=
nil
{
return
nil
,
err
}
}
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
oldLoadBin
=
"/Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs"
const
newLoadBin
=
"/Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse"
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
,
opts
*
MountOptions
)
error
{
return
syscall
.
Unmount
(
dir
,
0
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/mount_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"os"
"os/exec"
"path"
"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 without using
// fusermount.
func
mountDirect
(
mountPoint
string
,
opts
*
MountOptions
,
ready
chan
<-
error
)
(
fd
int
,
err
error
)
{
fd
,
err
=
syscall
.
Open
(
"/dev/fuse"
,
os
.
O_RDWR
,
0
)
// use syscall.Open since we want an int fd
if
err
!=
nil
{
return
}
// managed to open dev/fuse, attempt to mount
source
:=
opts
.
FsName
if
source
==
""
{
source
=
opts
.
Name
}
var
flags
uintptr
flags
|=
syscall
.
MS_NOSUID
|
syscall
.
MS_NODEV
// some values we need to pass to mount, but override possible since opts.Options comes after
var
r
=
[]
string
{
fmt
.
Sprintf
(
"fd=%d"
,
fd
),
"rootmode=40000"
,
"user_id=0"
,
"group_id=0"
,
}
r
=
append
(
r
,
opts
.
Options
...
)
if
opts
.
AllowOther
{
r
=
append
(
r
,
"allow_other"
)
}
err
=
syscall
.
Mount
(
opts
.
FsName
,
mountPoint
,
"fuse."
+
opts
.
Name
,
opts
.
DirectMountFlags
,
strings
.
Join
(
r
,
","
))
if
err
!=
nil
{
syscall
.
Close
(
fd
)
return
}
// success
close
(
ready
)
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
)
{
if
opts
.
DirectMount
{
fd
,
err
:=
mountDirect
(
mountPoint
,
opts
,
ready
)
if
err
==
nil
{
return
fd
,
nil
}
else
if
opts
.
Debug
{
log
.
Printf
(
"mount: failed to do direct mount: %s"
,
err
)
}
}
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
}
// golang sets CLOEXEC on file descriptors when they are
// acquired through normal operations (e.g. open).
// Buf for fd, we have to set CLOEXEC manually
syscall
.
CloseOnExec
(
fd
)
close
(
ready
)
return
fd
,
err
}
func
unmount
(
mountPoint
string
,
opts
*
MountOptions
)
(
err
error
)
{
if
opts
.
DirectMount
{
// Attempt to directly unmount, if fails fallback to fusermount method
err
:=
syscall
.
Unmount
(
mountPoint
,
0
)
if
err
==
nil
{
return
nil
}
}
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"
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/api.go
deleted
100644 → 0
View file @
e3e61d67
// 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.
// This package is deprecated. New projects should use the package
// "github.com/hanwen/go-fuse/v2/fs" instead.
//
// 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/v2/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 may be called on nodes that are
// already known.
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
)
// File locking
//
// GetLk returns existing lock information for file.
GetLk
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
// Sets or clears the lock described by lk on file.
SetLk
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
// Sets or clears the lock described by lk. This call blocks until the operation can be completed.
SetLkw
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
context
*
fuse
.
Context
)
(
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. This
// is useful in that PathFS API, where Create/Open have no
// access to the Inode at hand.
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
,
ctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
Write
(
data
[]
byte
,
off
int64
,
ctx
*
fuse
.
Context
)
(
written
uint32
,
code
fuse
.
Status
)
// File locking
GetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
SetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
SetLkw
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
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
(
ctx
*
fuse
.
Context
)
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
()
// XXX +ctx ?
Fsync
(
flags
int
,
ctx
*
fuse
.
Context
)
(
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
,
ctx
*
fuse
.
Context
)
fuse
.
Status
GetAttr
(
out
*
fuse
.
Attr
,
ctx
*
fuse
.
Context
)
fuse
.
Status
Chown
(
uid
uint32
,
gid
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
Chmod
(
perms
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
Utimens
(
atime
*
time
.
Time
,
mtime
*
time
.
Time
,
ctx
*
fuse
.
Context
)
fuse
.
Status
Allocate
(
off
uint64
,
size
uint64
,
mode
uint32
,
ctx
*
fuse
.
Context
)
(
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
// If set, issue Lookup rather than GetAttr calls for known
// children. This allows the filesystem to update its inode
// hierarchy in response to kernel calls.
LookupKnownChildren
bool
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultfile.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
,
ctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
{
return
nil
,
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Write
(
data
[]
byte
,
off
int64
,
ctx
*
fuse
.
Context
)
(
uint32
,
fuse
.
Status
)
{
return
0
,
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
GetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
SetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
SetLkw
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Flush
(
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
OK
}
func
(
f
*
defaultFile
)
Release
()
{
}
func
(
f
*
defaultFile
)
GetAttr
(
_
*
fuse
.
Attr
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Fsync
(
flags
int
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Utimens
(
atime
*
time
.
Time
,
mtime
*
time
.
Time
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Truncate
(
size
uint64
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Chown
(
uid
uint32
,
gid
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Chmod
(
perms
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
func
(
f
*
defaultFile
)
Allocate
(
off
uint64
,
size
uint64
,
mode
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/defaultnode.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
,
context
)
}
if
n
.
Inode
()
.
IsDir
()
{
out
.
Mode
=
fuse
.
S_IFDIR
|
0755
}
else
{
out
.
Mode
=
fuse
.
S_IFREG
|
0644
}
return
fuse
.
OK
}
func
(
n
*
defaultNode
)
GetLk
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
n
*
defaultNode
)
SetLk
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
func
(
n
*
defaultNode
)
SetLkw
(
file
File
,
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
context
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
ENOSYS
}
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
,
context
)
}
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
,
context
)
}
return
0
,
fuse
.
ENOSYS
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/dir.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/fuse"
)
type
connectorDir
struct
{
node
Node
inode
*
Inode
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
}
func
(
d
*
connectorDir
)
ReadDir
(
cancel
<-
chan
struct
{},
input
*
fuse
.
ReadIn
,
out
*
fuse
.
DirEntryList
)
(
code
fuse
.
Status
)
{
d
.
mu
.
Lock
()
defer
d
.
mu
.
Unlock
()
// rewinddir() should be as if reopening directory.
// TODO - test this.
if
d
.
stream
==
nil
||
input
.
Offset
==
0
{
d
.
stream
,
code
=
d
.
node
.
OpenDir
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
!
code
.
Ok
()
{
return
code
}
d
.
stream
=
append
(
d
.
stream
,
d
.
inode
.
getMountDirEntries
()
...
)
d
.
stream
=
append
(
d
.
stream
,
fuse
.
DirEntry
{
Mode
:
fuse
.
S_IFDIR
,
Name
:
"."
},
fuse
.
DirEntry
{
Mode
:
fuse
.
S_IFDIR
,
Name
:
".."
})
}
if
input
.
Offset
>
uint64
(
len
(
d
.
stream
))
{
// See https://github.com/hanwen/go-fuse/issues/297
// This can happen for FUSE exported over NFS. This
// seems incorrect, (maybe the kernel is using offsets
// from other opendir/readdir calls), it is harmless to reinforce that
// we have reached EOF.
return
fuse
.
OK
}
todo
:=
d
.
stream
[
input
.
Offset
:
]
for
_
,
e
:=
range
todo
{
if
e
.
Name
==
""
{
log
.
Printf
(
"got empty directory entry, mode %o."
,
e
.
Mode
)
continue
}
ok
:=
out
.
AddDirEntry
(
e
)
if
!
ok
{
break
}
}
return
fuse
.
OK
}
func
(
d
*
connectorDir
)
ReadDirPlus
(
cancel
<-
chan
struct
{},
input
*
fuse
.
ReadIn
,
out
*
fuse
.
DirEntryList
)
(
code
fuse
.
Status
)
{
d
.
mu
.
Lock
()
defer
d
.
mu
.
Unlock
()
// rewinddir() should be as if reopening directory.
if
d
.
stream
==
nil
||
input
.
Offset
==
0
{
d
.
stream
,
code
=
d
.
node
.
OpenDir
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
!
code
.
Ok
()
{
return
code
}
d
.
stream
=
append
(
d
.
stream
,
d
.
inode
.
getMountDirEntries
()
...
)
d
.
stream
=
append
(
d
.
stream
,
fuse
.
DirEntry
{
Mode
:
fuse
.
S_IFDIR
,
Name
:
"."
},
fuse
.
DirEntry
{
Mode
:
fuse
.
S_IFDIR
,
Name
:
".."
})
}
if
input
.
Offset
>
uint64
(
len
(
d
.
stream
))
{
// See comment in Readdir
return
fuse
.
OK
}
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
:=
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
}
d
.
rawFS
.
Lookup
(
cancel
,
&
input
.
InHeader
,
e
.
Name
,
entryDest
)
}
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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
,
ctx
*
fuse
.
Context
)
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
,
ctx
*
fuse
.
Context
)
(
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
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
OK
}
func
(
f
*
devNullFile
)
String
()
string
{
return
"devNullFile"
}
func
(
f
*
devNullFile
)
Read
(
buf
[]
byte
,
off
int64
,
ctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
{
return
fuse
.
ReadResultData
(
nil
),
fuse
.
OK
}
func
(
f
*
devNullFile
)
Write
(
content
[]
byte
,
off
int64
,
ctx
*
fuse
.
Context
)
(
uint32
,
fuse
.
Status
)
{
return
uint32
(
len
(
content
)),
fuse
.
OK
}
func
(
f
*
devNullFile
)
Flush
(
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
OK
}
func
(
f
*
devNullFile
)
Fsync
(
flags
int
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
OK
}
func
(
f
*
devNullFile
)
Truncate
(
size
uint64
,
ctx
*
fuse
.
Context
)
(
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
,
ctx
*
fuse
.
Context
)
(
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
,
ctx
*
fuse
.
Context
)
(
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
(
ctx
*
fuse
.
Context
)
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
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
lock
.
Lock
()
r
:=
fuse
.
ToStatus
(
syscall
.
Fsync
(
int
(
f
.
File
.
Fd
())))
f
.
lock
.
Unlock
()
return
r
}
const
(
F_OFD_GETLK
=
36
F_OFD_SETLK
=
37
F_OFD_SETLKW
=
38
)
func
(
f
*
loopbackFile
)
GetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
flk
:=
syscall
.
Flock_t
{}
lk
.
ToFlockT
(
&
flk
)
code
=
fuse
.
ToStatus
(
syscall
.
FcntlFlock
(
f
.
File
.
Fd
(),
F_OFD_GETLK
,
&
flk
))
out
.
FromFlockT
(
&
flk
)
return
}
func
(
f
*
loopbackFile
)
SetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
f
.
setLock
(
owner
,
lk
,
flags
,
false
)
}
func
(
f
*
loopbackFile
)
SetLkw
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
f
.
setLock
(
owner
,
lk
,
flags
,
true
)
}
func
(
f
*
loopbackFile
)
setLock
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
blocking
bool
)
(
code
fuse
.
Status
)
{
if
(
flags
&
fuse
.
FUSE_LK_FLOCK
)
!=
0
{
var
op
int
switch
lk
.
Typ
{
case
syscall
.
F_RDLCK
:
op
=
syscall
.
LOCK_SH
case
syscall
.
F_WRLCK
:
op
=
syscall
.
LOCK_EX
case
syscall
.
F_UNLCK
:
op
=
syscall
.
LOCK_UN
default
:
return
fuse
.
EINVAL
}
if
!
blocking
{
op
|=
syscall
.
LOCK_NB
}
return
fuse
.
ToStatus
(
syscall
.
Flock
(
int
(
f
.
File
.
Fd
()),
op
))
}
else
{
flk
:=
syscall
.
Flock_t
{}
lk
.
ToFlockT
(
&
flk
)
var
op
int
if
blocking
{
op
=
F_OFD_SETLKW
}
else
{
op
=
F_OFD_SETLK
}
return
fuse
.
ToStatus
(
syscall
.
FcntlFlock
(
f
.
File
.
Fd
(),
op
,
&
flk
))
}
}
func
(
f
*
loopbackFile
)
Truncate
(
size
uint64
,
ctx
*
fuse
.
Context
)
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
,
ctx
*
fuse
.
Context
)
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
,
ctx
*
fuse
.
Context
)
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
,
ctx
*
fuse
.
Context
)
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 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
,
ctx
*
fuse
.
Context
)
(
uint32
,
fuse
.
Status
)
{
return
0
,
fuse
.
EPERM
}
func
(
f
*
readOnlyFile
)
Fsync
(
flag
int
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
return
fuse
.
OK
}
func
(
f
*
readOnlyFile
)
Truncate
(
size
uint64
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
EPERM
}
func
(
f
*
readOnlyFile
)
Chmod
(
mode
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
EPERM
}
func
(
f
*
readOnlyFile
)
Chown
(
uid
uint32
,
gid
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
EPERM
}
func
(
f
*
readOnlyFile
)
Allocate
(
off
uint64
,
sz
uint64
,
mode
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
return
fuse
.
EPERM
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/fuse"
"github.com/hanwen/go-fuse/v2/internal/utimens"
)
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
}
// 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
}
// MacOS before High Sierra lacks utimensat() and UTIME_OMIT.
// We emulate using utimes() and extra GetAttr() calls.
func
(
f
*
loopbackFile
)
Utimens
(
a
*
time
.
Time
,
m
*
time
.
Time
)
fuse
.
Status
{
var
attr
fuse
.
Attr
if
a
==
nil
||
m
==
nil
{
var
status
fuse
.
Status
status
=
f
.
GetAttr
(
&
attr
)
if
!
status
.
Ok
()
{
return
status
}
}
tv
:=
utimens
.
Fill
(
a
,
m
,
&
attr
)
f
.
lock
.
Lock
()
err
:=
syscall
.
Futimes
(
int
(
f
.
File
.
Fd
()),
tv
)
f
.
lock
.
Unlock
()
return
fuse
.
ToStatus
(
err
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/files_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/fuse"
)
func
(
f
*
loopbackFile
)
Allocate
(
off
uint64
,
sz
uint64
,
mode
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
lock
.
Lock
()
err
:=
syscall
.
Fallocate
(
int
(
f
.
File
.
Fd
()),
mode
,
int64
(
off
),
int64
(
sz
))
// XXX cancel not propagated
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
,
ctx
*
fuse
.
Context
)
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
)
// XXX cancel not propagated
f
.
lock
.
Unlock
()
return
fuse
.
ToStatus
(
err
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsconnector.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"sync"
"time"
"unsafe"
"github.com/hanwen/go-fuse/v2/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
// This lock prevents Lookup() and Forget() from running concurrently.
// Locking at this level is a big hammer, but makes sure we don't return
// forgotten nodes to the kernel. Problems solved by this lock:
// https://github.com/hanwen/go-fuse/issues/168
// https://github.com/rfjakob/gocryptfs/issues/322
//
// The lock is shared: several concurrent Lookups are allowed to be
// run simultaneously, while Forget is exclusive.
lookupLock
sync
.
RWMutex
}
// 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
(
&
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
(
nil
,
&
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 i%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
)
}
// FileNotifyStoreCache notifies the kernel about changed data of the inode.
//
// This call is similar to FileNotify, but instead of only invalidating a data
// region, it puts updated data directly to the kernel cache:
//
// After this call completes, the kernel has put updated data into the inode's cache,
// and will use data from that cache for non direct-IO reads from the inode
// in corresponding data region. After kernel's cache data is evicted, the kernel
// will have to issue new Read calls on user request to get data content.
//
// ENOENT is returned if the kernel does not currently have entry for this
// inode in its dentry cache.
func
(
c
*
FileSystemConnector
)
FileNotifyStoreCache
(
node
*
Inode
,
off
int64
,
data
[]
byte
)
fuse
.
Status
{
var
nID
uint64
if
node
==
c
.
rootNode
{
nID
=
fuse
.
FUSE_ROOT_ID
}
else
{
nID
=
c
.
inodeMap
.
Handle
(
&
node
.
handled
)
}
if
nID
==
0
{
// the kernel does not currently know about this inode.
return
fuse
.
ENOENT
}
return
c
.
server
.
InodeNotifyStoreCache
(
nID
,
off
,
data
)
}
// FileRetrieveCache retrieves data from kernel's inode cache.
//
// This call retrieves data from kernel's inode cache @ offset and up to
// len(dest) bytes. If kernel cache has fewer consecutive data starting at
// offset, that fewer amount is returned. In particular if inode data at offset
// is not cached (0, OK) is returned.
//
// If the kernel does not currently have entry for this inode in its dentry
// cache (0, OK) is still returned, pretending that the inode could be known to
// the kernel, but kernel's inode cache is empty.
func
(
c
*
FileSystemConnector
)
FileRetrieveCache
(
node
*
Inode
,
off
int64
,
dest
[]
byte
)
(
n
int
,
st
fuse
.
Status
)
{
var
nID
uint64
if
node
==
c
.
rootNode
{
nID
=
fuse
.
FUSE_ROOT_ID
}
else
{
nID
=
c
.
inodeMap
.
Handle
(
&
node
.
handled
)
}
if
nID
==
0
{
// the kernel does not currently know about this inode.
// -> we can pretend that its cache for the inode is empty.
return
0
,
fuse
.
OK
}
return
c
.
server
.
InodeRetrieveCache
(
nID
,
off
,
dest
)
}
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsmount.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
=
*
m
.
options
.
Owner
}
}
func
(
m
*
fileSystemMount
)
fillEntry
(
out
*
fuse
.
EntryOut
)
{
out
.
SetEntryTimeout
(
m
.
options
.
EntryTimeout
)
out
.
SetAttrTimeout
(
m
.
options
.
AttrTimeout
)
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
)
{
out
.
SetTimeout
(
m
.
options
.
AttrTimeout
)
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
}
// registerFileHandle registers f or dir to have a handle.
//
// The handle is then used as file-handle in communications with kernel.
//
// If dir != nil the handle is registered for OpenDir and the inner file (see
// below) must be nil. If dir = nil the handle is registered for regular open &
// friends.
//
// f can be nil, or a WithFlags that leads to File=nil. For !OpenDir, if that
// is the case, returned handle will be 0 to indicate a handleless open, and
// the filesystem operations on the opened file will be routed to be served by
// the node.
//
// other arguments:
//
// node - Inode for which f or dir were opened,
// flags - file open flags, like O_RDWR.
func
(
m
*
fileSystemMount
)
registerFileHandle
(
node
*
Inode
,
dir
*
connectorDir
,
f
File
,
flags
uint32
)
(
handle
uint64
,
opened
*
openedFile
)
{
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
}
// don't allow both dir and file
if
dir
!=
nil
&&
b
.
WithFlags
.
File
!=
nil
{
panic
(
"registerFileHandle: both dir and file are set."
)
}
if
b
.
WithFlags
.
File
==
nil
&&
dir
==
nil
{
// it was just WithFlags{...}, but the file itself is nil
return
0
,
b
}
if
b
.
WithFlags
.
File
!=
nil
{
b
.
WithFlags
.
File
.
SetInode
(
node
)
}
node
.
openFilesMutex
.
Lock
()
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
out
.
SetEntryTimeout
(
m
.
options
.
NegativeTimeout
)
return
true
}
return
false
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fsops.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
"fmt"
"log"
"strings"
"time"
"github.com/hanwen/go-fuse/v2/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
(
cancel
<-
chan
struct
{},
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
),
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
return
fuse
.
ENOSYS
}
func
(
c
*
rawBridge
)
SetDebug
(
debug
bool
)
{
c
.
fsConn
()
.
SetDebug
(
debug
)
}
func
(
c
*
rawBridge
)
FsyncDir
(
cancel
<-
chan
struct
{},
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
(
cancel
<-
chan
struct
{},
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
.
mount
.
options
.
LookupKnownChildren
{
code
=
child
.
fsInode
.
GetAttr
(
out
,
nil
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
else
{
child
,
code
=
parent
.
fsInode
.
Lookup
(
out
,
name
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
return
child
,
code
}
func
(
c
*
rawBridge
)
Lookup
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
name
string
,
out
*
fuse
.
EntryOut
)
(
code
fuse
.
Status
)
{
// Prevent Lookup() and Forget() from running concurrently.
// Allow several Lookups to be run simultaneously.
c
.
lookupLock
.
RLock
()
defer
c
.
lookupLock
.
RUnlock
()
parent
:=
c
.
toInode
(
header
.
NodeId
)
if
!
parent
.
IsDir
()
{
log
.
Printf
(
"Lookup %q called on non-Directory node %d"
,
name
,
header
.
NodeId
)
return
fuse
.
ENOTDIR
}
child
,
code
:=
c
.
fsConn
()
.
internalLookup
(
cancel
,
&
out
.
Attr
,
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
)
{
// Prevent Lookup() and Forget() from running concurrently.
c
.
lookupLock
.
Lock
()
defer
c
.
lookupLock
.
Unlock
()
c
.
fsConn
()
.
forgetUpdate
(
nodeID
,
int
(
nlookup
))
}
func
(
c
*
rawBridge
)
GetAttr
(
cancel
<-
chan
struct
{},
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
:=
&
out
.
Attr
code
=
node
.
fsInode
.
GetAttr
(
dest
,
f
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
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
(
cancel
<-
chan
struct
{},
input
*
fuse
.
OpenIn
,
out
*
fuse
.
OpenOut
)
(
code
fuse
.
Status
)
{
node
:=
c
.
toInode
(
input
.
NodeId
)
de
:=
&
connectorDir
{
inode
:
node
,
node
:
node
.
Node
(),
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
(
cancel
<-
chan
struct
{},
input
*
fuse
.
ReadIn
,
out
*
fuse
.
DirEntryList
)
fuse
.
Status
{
node
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
dir
.
ReadDir
(
cancel
,
input
,
out
)
}
func
(
c
*
rawBridge
)
ReadDirPlus
(
cancel
<-
chan
struct
{},
input
*
fuse
.
ReadIn
,
out
*
fuse
.
DirEntryList
)
fuse
.
Status
{
node
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
opened
.
dir
.
ReadDirPlus
(
cancel
,
input
,
out
)
}
func
(
c
*
rawBridge
)
Open
(
cancel
<-
chan
struct
{},
input
*
fuse
.
OpenIn
,
out
*
fuse
.
OpenOut
)
(
status
fuse
.
Status
)
{
node
:=
c
.
toInode
(
input
.
NodeId
)
f
,
code
:=
node
.
fsInode
.
Open
(
input
.
Flags
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
!
code
.
Ok
()
{
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
(
cancel
<-
chan
struct
{},
input
*
fuse
.
SetAttrIn
,
out
*
fuse
.
AttrOut
)
(
code
fuse
.
Status
)
{
node
:=
c
.
toInode
(
input
.
NodeId
)
var
f
File
if
fh
,
ok
:=
input
.
GetFh
();
ok
{
if
opened
:=
node
.
mount
.
getOpenedFile
(
fh
);
opened
!=
nil
{
f
=
opened
.
WithFlags
.
File
}
}
if
permissions
,
ok
:=
input
.
GetMode
();
ok
{
code
=
node
.
fsInode
.
Chmod
(
f
,
permissions
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
uid
,
uok
:=
input
.
GetUID
()
gid
,
gok
:=
input
.
GetGID
()
if
code
.
Ok
()
&&
(
uok
||
gok
)
{
code
=
node
.
fsInode
.
Chown
(
f
,
uid
,
gid
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
if
sz
,
ok
:=
input
.
GetSize
();
code
.
Ok
()
&&
ok
{
code
=
node
.
fsInode
.
Truncate
(
f
,
sz
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
atime
,
aok
:=
input
.
GetATime
()
mtime
,
mok
:=
input
.
GetMTime
()
if
code
.
Ok
()
&&
(
aok
||
mok
)
{
var
a
,
m
*
time
.
Time
if
aok
{
a
=
&
atime
}
if
mok
{
m
=
&
mtime
}
code
=
node
.
fsInode
.
Utimens
(
f
,
a
,
m
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
if
!
code
.
Ok
()
{
return
code
}
// Must call GetAttr(); the filesystem may override some of
// the changes we effect here.
attr
:=
&
out
.
Attr
code
=
node
.
fsInode
.
GetAttr
(
attr
,
nil
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
code
.
Ok
()
{
node
.
mount
.
fillAttr
(
out
,
input
.
NodeId
)
}
return
code
}
func
(
c
*
rawBridge
)
Fallocate
(
cancel
<-
chan
struct
{},
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
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Readlink
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
)
(
out
[]
byte
,
code
fuse
.
Status
)
{
n
:=
c
.
toInode
(
header
.
NodeId
)
return
n
.
fsInode
.
Readlink
(
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Mknod
(
cancel
<-
chan
struct
{},
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
),
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
code
.
Ok
()
{
c
.
childLookup
(
out
,
child
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
code
=
child
.
fsInode
.
GetAttr
(
&
out
.
Attr
,
nil
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
return
code
}
func
(
c
*
rawBridge
)
Mkdir
(
cancel
<-
chan
struct
{},
input
*
fuse
.
MkdirIn
,
name
string
,
out
*
fuse
.
EntryOut
)
(
code
fuse
.
Status
)
{
parent
:=
c
.
toInode
(
input
.
NodeId
)
child
,
code
:=
parent
.
fsInode
.
Mkdir
(
name
,
input
.
Mode
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
code
.
Ok
()
{
c
.
childLookup
(
out
,
child
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
code
=
child
.
fsInode
.
GetAttr
(
&
out
.
Attr
,
nil
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
return
code
}
func
(
c
*
rawBridge
)
Unlink
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
return
parent
.
fsInode
.
Unlink
(
name
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Rmdir
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
name
string
)
(
code
fuse
.
Status
)
{
parent
:=
c
.
toInode
(
header
.
NodeId
)
return
parent
.
fsInode
.
Rmdir
(
name
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Symlink
(
cancel
<-
chan
struct
{},
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
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
if
code
.
Ok
()
{
c
.
childLookup
(
out
,
child
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
code
=
child
.
fsInode
.
GetAttr
(
&
out
.
Attr
,
nil
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
return
code
}
func
(
c
*
rawBridge
)
Rename
(
cancel
<-
chan
struct
{},
input
*
fuse
.
RenameIn
,
oldName
string
,
newName
string
)
(
code
fuse
.
Status
)
{
if
input
.
Flags
!=
0
{
return
fuse
.
ENOSYS
}
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
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Link
(
cancel
<-
chan
struct
{},
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
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
code
.
Ok
()
{
c
.
childLookup
(
out
,
child
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
code
=
child
.
fsInode
.
GetAttr
(
&
out
.
Attr
,
nil
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
return
code
}
func
(
c
*
rawBridge
)
Access
(
cancel
<-
chan
struct
{},
input
*
fuse
.
AccessIn
)
(
code
fuse
.
Status
)
{
n
:=
c
.
toInode
(
input
.
NodeId
)
return
n
.
fsInode
.
Access
(
input
.
Mask
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Create
(
cancel
<-
chan
struct
{},
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
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
if
!
code
.
Ok
()
{
return
code
}
c
.
childLookup
(
&
out
.
EntryOut
,
child
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
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
(
cancel
<-
chan
struct
{},
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
)
GetXAttr
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
attribute
string
,
dest
[]
byte
)
(
sz
uint32
,
code
fuse
.
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
data
,
errno
:=
node
.
fsInode
.
GetXAttr
(
attribute
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
if
len
(
data
)
>
len
(
dest
)
{
return
uint32
(
len
(
data
)),
fuse
.
ERANGE
}
copy
(
dest
,
data
)
return
uint32
(
len
(
data
)),
errno
}
func
(
c
*
rawBridge
)
GetXAttrData
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
attribute
string
)
(
data
[]
byte
,
code
fuse
.
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
fsInode
.
GetXAttr
(
attribute
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
RemoveXAttr
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
attr
string
)
fuse
.
Status
{
node
:=
c
.
toInode
(
header
.
NodeId
)
return
node
.
fsInode
.
RemoveXAttr
(
attr
,
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
SetXAttr
(
cancel
<-
chan
struct
{},
input
*
fuse
.
SetXAttrIn
,
attr
string
,
data
[]
byte
)
fuse
.
Status
{
node
:=
c
.
toInode
(
input
.
NodeId
)
return
node
.
fsInode
.
SetXAttr
(
attr
,
data
,
int
(
input
.
Flags
),
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
ListXAttr
(
cancel
<-
chan
struct
{},
header
*
fuse
.
InHeader
,
dest
[]
byte
)
(
uint32
,
fuse
.
Status
)
{
node
:=
c
.
toInode
(
header
.
NodeId
)
attrs
,
code
:=
node
.
fsInode
.
ListXAttr
(
&
fuse
.
Context
{
Caller
:
header
.
Caller
,
Cancel
:
cancel
})
if
code
!=
fuse
.
OK
{
return
0
,
code
}
var
sz
uint32
for
_
,
v
:=
range
attrs
{
sz
+=
uint32
(
len
(
v
))
+
1
}
if
int
(
sz
)
>
len
(
dest
)
{
return
sz
,
fuse
.
ERANGE
}
dest
=
dest
[
:
0
]
for
_
,
v
:=
range
attrs
{
dest
=
append
(
dest
,
v
...
)
dest
=
append
(
dest
,
0
)
}
return
sz
,
code
}
////////////////
// files.
func
(
c
*
rawBridge
)
Write
(
cancel
<-
chan
struct
{},
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
),
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
Read
(
cancel
<-
chan
struct
{},
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
),
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
GetLk
(
cancel
<-
chan
struct
{},
input
*
fuse
.
LkIn
,
out
*
fuse
.
LkOut
)
(
code
fuse
.
Status
)
{
n
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
n
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
n
.
fsInode
.
GetLk
(
opened
,
input
.
Owner
,
&
input
.
Lk
,
input
.
LkFlags
,
&
out
.
Lk
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
SetLk
(
cancel
<-
chan
struct
{},
input
*
fuse
.
LkIn
)
(
code
fuse
.
Status
)
{
n
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
n
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
n
.
fsInode
.
SetLk
(
opened
,
input
.
Owner
,
&
input
.
Lk
,
input
.
LkFlags
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
SetLkw
(
cancel
<-
chan
struct
{},
input
*
fuse
.
LkIn
)
(
code
fuse
.
Status
)
{
n
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
n
.
mount
.
getOpenedFile
(
input
.
Fh
)
return
n
.
fsInode
.
SetLkw
(
opened
,
input
.
Owner
,
&
input
.
Lk
,
input
.
LkFlags
,
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
func
(
c
*
rawBridge
)
StatFs
(
cancel
<-
chan
struct
{},
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
(
cancel
<-
chan
struct
{},
input
*
fuse
.
FlushIn
)
fuse
.
Status
{
node
:=
c
.
toInode
(
input
.
NodeId
)
opened
:=
node
.
mount
.
getOpenedFile
(
input
.
Fh
)
if
opened
!=
nil
{
return
opened
.
WithFlags
.
File
.
Flush
(
&
fuse
.
Context
{
Caller
:
input
.
Caller
,
Cancel
:
cancel
})
}
return
fuse
.
OK
}
func
(
c
*
rawBridge
)
CopyFileRange
(
cancel
<-
chan
struct
{},
input
*
fuse
.
CopyFileRangeIn
)
(
written
uint32
,
code
fuse
.
Status
)
{
return
0
,
fuse
.
ENOSYS
}
func
(
fs
*
rawBridge
)
Lseek
(
cancel
<-
chan
struct
{},
in
*
fuse
.
LseekIn
,
out
*
fuse
.
LseekOut
)
fuse
.
Status
{
return
fuse
.
ENOSYS
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/fuse.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/fuse"
)
// Mount mounts a filesystem with the given root node on the given directory.
// Convenience wrapper around fuse.NewServer
func
Mount
(
mountpoint
string
,
root
Node
,
mountOptions
*
fuse
.
MountOptions
,
nodefsOptions
*
Options
)
(
*
fuse
.
Server
,
*
FileSystemConnector
,
error
)
{
conn
:=
NewFileSystemConnector
(
root
,
nodefsOptions
)
s
,
err
:=
fuse
.
NewServer
(
conn
.
RawFS
(),
mountpoint
,
mountOptions
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
return
s
,
conn
,
nil
}
// MountRoot is like Mount but uses default fuse mount options.
func
MountRoot
(
mountpoint
string
,
root
Node
,
opts
*
Options
)
(
*
fuse
.
Server
,
*
FileSystemConnector
,
error
)
{
mountOpts
:=
&
fuse
.
MountOptions
{}
if
opts
!=
nil
&&
opts
.
Debug
{
mountOpts
.
Debug
=
opts
.
Debug
}
return
Mount
(
mountpoint
,
root
,
mountOpts
,
opts
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/handle.go
deleted
100644 → 0
View file @
e3e61d67
// 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
{
handle
uint64
generation
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
()
defer
m
.
Unlock
()
// Reuse existing handle
if
obj
.
count
!=
0
{
obj
.
count
++
return
obj
.
handle
,
obj
.
generation
}
// Create a new handle number or recycle one on from the free list
if
len
(
m
.
freeIds
)
==
0
{
obj
.
handle
=
uint64
(
len
(
m
.
handles
))
m
.
handles
=
append
(
m
.
handles
,
obj
)
}
else
{
obj
.
handle
=
m
.
freeIds
[
len
(
m
.
freeIds
)
-
1
]
m
.
freeIds
=
m
.
freeIds
[
:
len
(
m
.
freeIds
)
-
1
]
m
.
handles
[
obj
.
handle
]
=
obj
}
// Increment generation number to guarantee the (handle, generation) tuple
// is unique
m
.
generation
++
m
.
used
++
obj
.
generation
=
m
.
generation
obj
.
count
++
return
obj
.
handle
,
obj
.
generation
}
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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/inode.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"log"
"sync"
"github.com/hanwen/go-fuse/v2/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
// 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.
// Print the inode. The default print method may not be used for
// debugging, as dumping the map requires synchronization.
func
(
n
*
Inode
)
String
()
string
{
return
fmt
.
Sprintf
(
"node{%d}"
,
n
.
handled
.
handle
)
}
// 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
,
""
}
n
.
mount
.
treeLock
.
RLock
()
defer
n
.
mount
.
treeLock
.
RUnlock
()
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
)
}
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/lockingfile.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
,
ctx
*
fuse
.
Context
)
(
fuse
.
ReadResult
,
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Read
(
buf
,
off
,
ctx
)
}
func
(
f
*
lockingFile
)
Write
(
data
[]
byte
,
off
int64
,
ctx
*
fuse
.
Context
)
(
uint32
,
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Write
(
data
,
off
,
ctx
)
}
func
(
f
*
lockingFile
)
Flush
(
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Flush
(
ctx
)
}
func
(
f
*
lockingFile
)
GetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
out
*
fuse
.
FileLock
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
GetLk
(
owner
,
lk
,
flags
,
out
,
ctx
)
}
func
(
f
*
lockingFile
)
SetLk
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
SetLk
(
owner
,
lk
,
flags
,
ctx
)
}
func
(
f
*
lockingFile
)
SetLkw
(
owner
uint64
,
lk
*
fuse
.
FileLock
,
flags
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
SetLkw
(
owner
,
lk
,
flags
,
ctx
)
}
func
(
f
*
lockingFile
)
Release
()
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
f
.
file
.
Release
()
}
func
(
f
*
lockingFile
)
GetAttr
(
a
*
fuse
.
Attr
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
GetAttr
(
a
,
ctx
)
}
func
(
f
*
lockingFile
)
Fsync
(
flags
int
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Fsync
(
flags
,
ctx
)
}
func
(
f
*
lockingFile
)
Utimens
(
atime
*
time
.
Time
,
mtime
*
time
.
Time
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Utimens
(
atime
,
mtime
,
ctx
)
}
func
(
f
*
lockingFile
)
Truncate
(
size
uint64
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Truncate
(
size
,
ctx
)
}
func
(
f
*
lockingFile
)
Chown
(
uid
uint32
,
gid
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Chown
(
uid
,
gid
,
ctx
)
}
func
(
f
*
lockingFile
)
Chmod
(
perms
uint32
,
ctx
*
fuse
.
Context
)
fuse
.
Status
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Chmod
(
perms
,
ctx
)
}
func
(
f
*
lockingFile
)
Allocate
(
off
uint64
,
size
uint64
,
mode
uint32
,
ctx
*
fuse
.
Context
)
(
code
fuse
.
Status
)
{
f
.
mu
.
Lock
()
defer
f
.
mu
.
Unlock
()
return
f
.
file
.
Allocate
(
off
,
size
,
mode
,
ctx
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/memnode.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
mu
sync
.
Mutex
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
)
{
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
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
(
ctx
*
fuse
.
Context
)
fuse
.
Status
{
code
:=
n
.
File
.
Flush
(
ctx
)
if
!
code
.
Ok
()
{
return
code
}
st
:=
syscall
.
Stat_t
{}
err
:=
syscall
.
Stat
(
n
.
node
.
filename
(),
&
st
)
n
.
node
.
mu
.
Lock
()
defer
n
.
node
.
mu
.
Unlock
()
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
)
{
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
*
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
,
context
)
}
else
{
err
:=
os
.
Truncate
(
n
.
filename
(),
int64
(
size
))
code
=
fuse
.
ToStatus
(
err
)
}
if
code
.
Ok
()
{
now
:=
time
.
Now
()
n
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
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
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
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
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
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
.
mu
.
Lock
()
defer
n
.
mu
.
Unlock
()
n
.
info
.
SetTimes
(
nil
,
nil
,
&
now
)
return
fuse
.
OK
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/nodefs/syscall_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/opcode.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"reflect"
"runtime"
"time"
"unsafe"
)
const
(
_OP_LOOKUP
=
uint32
(
1
)
_OP_FORGET
=
uint32
(
2
)
_OP_GETATTR
=
uint32
(
3
)
_OP_SETATTR
=
uint32
(
4
)
_OP_READLINK
=
uint32
(
5
)
_OP_SYMLINK
=
uint32
(
6
)
_OP_MKNOD
=
uint32
(
8
)
_OP_MKDIR
=
uint32
(
9
)
_OP_UNLINK
=
uint32
(
10
)
_OP_RMDIR
=
uint32
(
11
)
_OP_RENAME
=
uint32
(
12
)
_OP_LINK
=
uint32
(
13
)
_OP_OPEN
=
uint32
(
14
)
_OP_READ
=
uint32
(
15
)
_OP_WRITE
=
uint32
(
16
)
_OP_STATFS
=
uint32
(
17
)
_OP_RELEASE
=
uint32
(
18
)
_OP_FSYNC
=
uint32
(
20
)
_OP_SETXATTR
=
uint32
(
21
)
_OP_GETXATTR
=
uint32
(
22
)
_OP_LISTXATTR
=
uint32
(
23
)
_OP_REMOVEXATTR
=
uint32
(
24
)
_OP_FLUSH
=
uint32
(
25
)
_OP_INIT
=
uint32
(
26
)
_OP_OPENDIR
=
uint32
(
27
)
_OP_READDIR
=
uint32
(
28
)
_OP_RELEASEDIR
=
uint32
(
29
)
_OP_FSYNCDIR
=
uint32
(
30
)
_OP_GETLK
=
uint32
(
31
)
_OP_SETLK
=
uint32
(
32
)
_OP_SETLKW
=
uint32
(
33
)
_OP_ACCESS
=
uint32
(
34
)
_OP_CREATE
=
uint32
(
35
)
_OP_INTERRUPT
=
uint32
(
36
)
_OP_BMAP
=
uint32
(
37
)
_OP_DESTROY
=
uint32
(
38
)
_OP_IOCTL
=
uint32
(
39
)
_OP_POLL
=
uint32
(
40
)
_OP_NOTIFY_REPLY
=
uint32
(
41
)
_OP_BATCH_FORGET
=
uint32
(
42
)
_OP_FALLOCATE
=
uint32
(
43
)
// protocol version 19.
_OP_READDIRPLUS
=
uint32
(
44
)
// protocol version 21.
_OP_RENAME2
=
uint32
(
45
)
// protocol version 23.
_OP_LSEEK
=
uint32
(
46
)
// protocol version 24
_OP_COPY_FILE_RANGE
=
uint32
(
47
)
// protocol version 28.
// The following entries don't have to be compatible across Go-FUSE versions.
_OP_NOTIFY_INVAL_ENTRY
=
uint32
(
100
)
_OP_NOTIFY_INVAL_INODE
=
uint32
(
101
)
_OP_NOTIFY_STORE_CACHE
=
uint32
(
102
)
_OP_NOTIFY_RETRIEVE_CACHE
=
uint32
(
103
)
_OP_NOTIFY_DELETE
=
uint32
(
104
)
// protocol version 18
_OPCODE_COUNT
=
uint32
(
105
)
)
////////////////////////////////////////////////////////////////
func
doInit
(
server
*
Server
,
req
*
request
)
{
input
:=
(
*
InitIn
)(
req
.
inData
)
if
input
.
Major
!=
_FUSE_KERNEL_VERSION
{
log
.
Printf
(
"Major versions does not match. Given %d, want %d
\n
"
,
input
.
Major
,
_FUSE_KERNEL_VERSION
)
req
.
status
=
EIO
return
}
if
input
.
Minor
<
_MINIMUM_MINOR_VERSION
{
log
.
Printf
(
"Minor version is less than we support. Given %d, want at least %d
\n
"
,
input
.
Minor
,
_MINIMUM_MINOR_VERSION
)
req
.
status
=
EIO
return
}
server
.
reqMu
.
Lock
()
server
.
kernelSettings
=
*
input
server
.
kernelSettings
.
Flags
=
input
.
Flags
&
(
CAP_ASYNC_READ
|
CAP_BIG_WRITES
|
CAP_FILE_OPS
|
CAP_READDIRPLUS
|
CAP_NO_OPEN_SUPPORT
|
CAP_PARALLEL_DIROPS
)
if
server
.
opts
.
EnableLocks
{
server
.
kernelSettings
.
Flags
|=
CAP_FLOCK_LOCKS
|
CAP_POSIX_LOCKS
}
dataCacheMode
:=
input
.
Flags
&
CAP_AUTO_INVAL_DATA
if
server
.
opts
.
ExplicitDataCacheControl
{
// we don't want CAP_AUTO_INVAL_DATA even if we cannot go into fully explicit mode
dataCacheMode
=
0
explicit
:=
input
.
Flags
&
CAP_EXPLICIT_INVAL_DATA
if
explicit
!=
0
{
dataCacheMode
=
explicit
}
}
server
.
kernelSettings
.
Flags
|=
dataCacheMode
if
input
.
Minor
>=
13
{
server
.
setSplice
()
}
server
.
reqMu
.
Unlock
()
out
:=
(
*
InitOut
)(
req
.
outData
())
*
out
=
InitOut
{
Major
:
_FUSE_KERNEL_VERSION
,
Minor
:
_OUR_MINOR_VERSION
,
MaxReadAhead
:
input
.
MaxReadAhead
,
Flags
:
server
.
kernelSettings
.
Flags
,
MaxWrite
:
uint32
(
server
.
opts
.
MaxWrite
),
CongestionThreshold
:
uint16
(
server
.
opts
.
MaxBackground
*
3
/
4
),
MaxBackground
:
uint16
(
server
.
opts
.
MaxBackground
),
}
if
server
.
opts
.
MaxReadAhead
!=
0
&&
uint32
(
server
.
opts
.
MaxReadAhead
)
<
out
.
MaxReadAhead
{
out
.
MaxReadAhead
=
uint32
(
server
.
opts
.
MaxReadAhead
)
}
if
out
.
Minor
>
input
.
Minor
{
out
.
Minor
=
input
.
Minor
}
if
out
.
Minor
<=
22
{
tweaked
:=
*
req
.
handler
// v8-v22 don't have TimeGran and further fields.
tweaked
.
OutputSize
=
24
req
.
handler
=
&
tweaked
}
req
.
status
=
OK
}
func
doOpen
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
OpenOut
)(
req
.
outData
())
status
:=
server
.
fileSystem
.
Open
(
req
.
cancel
,
(
*
OpenIn
)(
req
.
inData
),
out
)
req
.
status
=
status
if
status
!=
OK
{
return
}
}
func
doCreate
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
CreateOut
)(
req
.
outData
())
status
:=
server
.
fileSystem
.
Create
(
req
.
cancel
,
(
*
CreateIn
)(
req
.
inData
),
req
.
filenames
[
0
],
out
)
req
.
status
=
status
}
func
doReadDir
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
ReadIn
)(
req
.
inData
)
buf
:=
server
.
allocOut
(
req
,
in
.
Size
)
out
:=
NewDirEntryList
(
buf
,
uint64
(
in
.
Offset
))
code
:=
server
.
fileSystem
.
ReadDir
(
req
.
cancel
,
in
,
out
)
req
.
flatData
=
out
.
bytes
()
req
.
status
=
code
}
func
doReadDirPlus
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
ReadIn
)(
req
.
inData
)
buf
:=
server
.
allocOut
(
req
,
in
.
Size
)
out
:=
NewDirEntryList
(
buf
,
uint64
(
in
.
Offset
))
code
:=
server
.
fileSystem
.
ReadDirPlus
(
req
.
cancel
,
in
,
out
)
req
.
flatData
=
out
.
bytes
()
req
.
status
=
code
}
func
doOpenDir
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
OpenOut
)(
req
.
outData
())
status
:=
server
.
fileSystem
.
OpenDir
(
req
.
cancel
,
(
*
OpenIn
)(
req
.
inData
),
out
)
req
.
status
=
status
}
func
doSetattr
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
AttrOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
SetAttr
(
req
.
cancel
,
(
*
SetAttrIn
)(
req
.
inData
),
out
)
}
func
doWrite
(
server
*
Server
,
req
*
request
)
{
n
,
status
:=
server
.
fileSystem
.
Write
(
req
.
cancel
,
(
*
WriteIn
)(
req
.
inData
),
req
.
arg
)
o
:=
(
*
WriteOut
)(
req
.
outData
())
o
.
Size
=
n
req
.
status
=
status
}
func
doNotifyReply
(
server
*
Server
,
req
*
request
)
{
reply
:=
(
*
NotifyRetrieveIn
)(
req
.
inData
)
server
.
retrieveMu
.
Lock
()
reading
:=
server
.
retrieveTab
[
reply
.
Unique
]
delete
(
server
.
retrieveTab
,
reply
.
Unique
)
server
.
retrieveMu
.
Unlock
()
badf
:=
func
(
format
string
,
argv
...
interface
{})
{
log
.
Printf
(
"notify reply: "
+
format
,
argv
...
)
}
if
reading
==
nil
{
badf
(
"unexpected unique - ignoring"
)
return
}
reading
.
n
=
0
reading
.
st
=
EIO
defer
close
(
reading
.
ready
)
if
reading
.
nodeid
!=
reply
.
NodeId
{
badf
(
"inode mismatch: expected %s, got %s"
,
reading
.
nodeid
,
reply
.
NodeId
)
return
}
if
reading
.
offset
!=
reply
.
Offset
{
badf
(
"offset mismatch: expected @%d, got @%d"
,
reading
.
offset
,
reply
.
Offset
)
return
}
if
len
(
reading
.
dest
)
<
len
(
req
.
arg
)
{
badf
(
"too much data: requested %db, got %db (will use only %db)"
,
len
(
reading
.
dest
),
len
(
req
.
arg
),
len
(
reading
.
dest
))
}
reading
.
n
=
copy
(
reading
.
dest
,
req
.
arg
)
reading
.
st
=
OK
}
const
_SECURITY_CAPABILITY
=
"security.capability"
const
_SECURITY_ACL
=
"system.posix_acl_access"
const
_SECURITY_ACL_DEFAULT
=
"system.posix_acl_default"
func
doGetXAttr
(
server
*
Server
,
req
*
request
)
{
if
server
.
opts
.
DisableXAttrs
{
req
.
status
=
ENOSYS
return
}
if
server
.
opts
.
IgnoreSecurityLabels
&&
req
.
inHeader
.
Opcode
==
_OP_GETXATTR
{
fn
:=
req
.
filenames
[
0
]
if
fn
==
_SECURITY_CAPABILITY
||
fn
==
_SECURITY_ACL_DEFAULT
||
fn
==
_SECURITY_ACL
{
req
.
status
=
ENOATTR
return
}
}
input
:=
(
*
GetXAttrIn
)(
req
.
inData
)
req
.
flatData
=
server
.
allocOut
(
req
,
input
.
Size
)
out
:=
(
*
GetXAttrOut
)(
req
.
outData
())
var
n
uint32
switch
req
.
inHeader
.
Opcode
{
case
_OP_GETXATTR
:
n
,
req
.
status
=
server
.
fileSystem
.
GetXAttr
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
0
],
req
.
flatData
)
case
_OP_LISTXATTR
:
n
,
req
.
status
=
server
.
fileSystem
.
ListXAttr
(
req
.
cancel
,
req
.
inHeader
,
req
.
flatData
)
default
:
req
.
status
=
ENOSYS
}
if
input
.
Size
==
0
&&
req
.
status
==
ERANGE
{
// For input.size==0, returning ERANGE is an error.
req
.
status
=
OK
out
.
Size
=
n
}
else
if
req
.
status
.
Ok
()
{
// ListXAttr called with an empty buffer returns the current size of
// the list but does not touch the buffer (see man 2 listxattr).
if
len
(
req
.
flatData
)
>
0
{
req
.
flatData
=
req
.
flatData
[
:
n
]
}
out
.
Size
=
n
}
else
{
req
.
flatData
=
req
.
flatData
[
:
0
]
}
}
func
doGetAttr
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
AttrOut
)(
req
.
outData
())
s
:=
server
.
fileSystem
.
GetAttr
(
req
.
cancel
,
(
*
GetAttrIn
)(
req
.
inData
),
out
)
req
.
status
=
s
}
// doForget - forget one NodeId
func
doForget
(
server
*
Server
,
req
*
request
)
{
if
!
server
.
opts
.
RememberInodes
{
server
.
fileSystem
.
Forget
(
req
.
inHeader
.
NodeId
,
(
*
ForgetIn
)(
req
.
inData
)
.
Nlookup
)
}
}
// doBatchForget - forget a list of NodeIds
func
doBatchForget
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
_BatchForgetIn
)(
req
.
inData
)
wantBytes
:=
uintptr
(
in
.
Count
)
*
unsafe
.
Sizeof
(
_ForgetOne
{})
if
uintptr
(
len
(
req
.
arg
))
<
wantBytes
{
// We have no return value to complain, so log an error.
log
.
Printf
(
"Too few bytes for batch forget. Got %d bytes, want %d (%d entries)"
,
len
(
req
.
arg
),
wantBytes
,
in
.
Count
)
}
h
:=
&
reflect
.
SliceHeader
{
Data
:
uintptr
(
unsafe
.
Pointer
(
&
req
.
arg
[
0
])),
Len
:
int
(
in
.
Count
),
Cap
:
int
(
in
.
Count
),
}
forgets
:=
*
(
*
[]
_ForgetOne
)(
unsafe
.
Pointer
(
h
))
for
i
,
f
:=
range
forgets
{
if
server
.
opts
.
Debug
{
log
.
Printf
(
"doBatchForget: rx %d %d/%d: FORGET i%d {Nlookup=%d}"
,
req
.
inHeader
.
Unique
,
i
+
1
,
len
(
forgets
),
f
.
NodeId
,
f
.
Nlookup
)
}
if
f
.
NodeId
==
pollHackInode
{
continue
}
server
.
fileSystem
.
Forget
(
f
.
NodeId
,
f
.
Nlookup
)
}
}
func
doReadlink
(
server
*
Server
,
req
*
request
)
{
req
.
flatData
,
req
.
status
=
server
.
fileSystem
.
Readlink
(
req
.
cancel
,
req
.
inHeader
)
}
func
doLookup
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
EntryOut
)(
req
.
outData
())
s
:=
server
.
fileSystem
.
Lookup
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
0
],
out
)
req
.
status
=
s
}
func
doMknod
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
EntryOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
Mknod
(
req
.
cancel
,
(
*
MknodIn
)(
req
.
inData
),
req
.
filenames
[
0
],
out
)
}
func
doMkdir
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
EntryOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
Mkdir
(
req
.
cancel
,
(
*
MkdirIn
)(
req
.
inData
),
req
.
filenames
[
0
],
out
)
}
func
doUnlink
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Unlink
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
0
])
}
func
doRmdir
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Rmdir
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
0
])
}
func
doLink
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
EntryOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
Link
(
req
.
cancel
,
(
*
LinkIn
)(
req
.
inData
),
req
.
filenames
[
0
],
out
)
}
func
doRead
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
ReadIn
)(
req
.
inData
)
buf
:=
server
.
allocOut
(
req
,
in
.
Size
)
req
.
readResult
,
req
.
status
=
server
.
fileSystem
.
Read
(
req
.
cancel
,
in
,
buf
)
if
fd
,
ok
:=
req
.
readResult
.
(
*
readResultFd
);
ok
{
req
.
fdData
=
fd
req
.
flatData
=
nil
}
else
if
req
.
readResult
!=
nil
&&
req
.
status
.
Ok
()
{
req
.
flatData
,
req
.
status
=
req
.
readResult
.
Bytes
(
buf
)
}
}
func
doFlush
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Flush
(
req
.
cancel
,
(
*
FlushIn
)(
req
.
inData
))
}
func
doRelease
(
server
*
Server
,
req
*
request
)
{
server
.
fileSystem
.
Release
(
req
.
cancel
,
(
*
ReleaseIn
)(
req
.
inData
))
}
func
doFsync
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Fsync
(
req
.
cancel
,
(
*
FsyncIn
)(
req
.
inData
))
}
func
doReleaseDir
(
server
*
Server
,
req
*
request
)
{
server
.
fileSystem
.
ReleaseDir
((
*
ReleaseIn
)(
req
.
inData
))
}
func
doFsyncDir
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
FsyncDir
(
req
.
cancel
,
(
*
FsyncIn
)(
req
.
inData
))
}
func
doSetXAttr
(
server
*
Server
,
req
*
request
)
{
splits
:=
bytes
.
SplitN
(
req
.
arg
,
[]
byte
{
0
},
2
)
req
.
status
=
server
.
fileSystem
.
SetXAttr
(
req
.
cancel
,
(
*
SetXAttrIn
)(
req
.
inData
),
string
(
splits
[
0
]),
splits
[
1
])
}
func
doRemoveXAttr
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
RemoveXAttr
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
0
])
}
func
doAccess
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Access
(
req
.
cancel
,
(
*
AccessIn
)(
req
.
inData
))
}
func
doSymlink
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
EntryOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
Symlink
(
req
.
cancel
,
req
.
inHeader
,
req
.
filenames
[
1
],
req
.
filenames
[
0
],
out
)
}
func
doRename
(
server
*
Server
,
req
*
request
)
{
in1
:=
(
*
Rename1In
)(
req
.
inData
)
in
:=
RenameIn
{
InHeader
:
in1
.
InHeader
,
Newdir
:
in1
.
Newdir
,
}
req
.
status
=
server
.
fileSystem
.
Rename
(
req
.
cancel
,
&
in
,
req
.
filenames
[
0
],
req
.
filenames
[
1
])
}
func
doRename2
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Rename
(
req
.
cancel
,
(
*
RenameIn
)(
req
.
inData
),
req
.
filenames
[
0
],
req
.
filenames
[
1
])
}
func
doStatFs
(
server
*
Server
,
req
*
request
)
{
out
:=
(
*
StatfsOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
StatFs
(
req
.
cancel
,
req
.
inHeader
,
out
)
if
req
.
status
==
ENOSYS
&&
runtime
.
GOOS
==
"darwin"
{
// OSX FUSE requires Statfs to be implemented for the
// mount to succeed.
*
out
=
StatfsOut
{}
req
.
status
=
OK
}
}
func
doIoctl
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
ENOSYS
}
func
doDestroy
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
OK
}
func
doFallocate
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
Fallocate
(
req
.
cancel
,
(
*
FallocateIn
)(
req
.
inData
))
}
func
doGetLk
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
GetLk
(
req
.
cancel
,
(
*
LkIn
)(
req
.
inData
),
(
*
LkOut
)(
req
.
outData
()))
}
func
doSetLk
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
SetLk
(
req
.
cancel
,
(
*
LkIn
)(
req
.
inData
))
}
func
doSetLkw
(
server
*
Server
,
req
*
request
)
{
req
.
status
=
server
.
fileSystem
.
SetLkw
(
req
.
cancel
,
(
*
LkIn
)(
req
.
inData
))
}
func
doLseek
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
LseekIn
)(
req
.
inData
)
out
:=
(
*
LseekOut
)(
req
.
outData
())
req
.
status
=
server
.
fileSystem
.
Lseek
(
req
.
cancel
,
in
,
out
)
}
func
doCopyFileRange
(
server
*
Server
,
req
*
request
)
{
in
:=
(
*
CopyFileRangeIn
)(
req
.
inData
)
out
:=
(
*
WriteOut
)(
req
.
outData
())
out
.
Size
,
req
.
status
=
server
.
fileSystem
.
CopyFileRange
(
req
.
cancel
,
in
)
}
func
doInterrupt
(
server
*
Server
,
req
*
request
)
{
input
:=
(
*
InterruptIn
)(
req
.
inData
)
server
.
reqMu
.
Lock
()
defer
server
.
reqMu
.
Unlock
()
// This is slow, but this operation is rare.
for
_
,
inflight
:=
range
server
.
reqInflight
{
if
input
.
Unique
==
inflight
.
inHeader
.
Unique
&&
!
inflight
.
interrupted
{
close
(
inflight
.
cancel
)
inflight
.
interrupted
=
true
req
.
status
=
OK
return
}
}
// not found; wait for a bit
time
.
Sleep
(
10
*
time
.
Microsecond
)
req
.
status
=
EAGAIN
}
////////////////////////////////////////////////////////////////
type
operationFunc
func
(
*
Server
,
*
request
)
type
castPointerFunc
func
(
unsafe
.
Pointer
)
interface
{}
type
operationHandler
struct
{
Name
string
Func
operationFunc
InputSize
uintptr
OutputSize
uintptr
DecodeIn
castPointerFunc
DecodeOut
castPointerFunc
FileNames
int
FileNameOut
bool
}
var
operationHandlers
[]
*
operationHandler
func
operationName
(
op
uint32
)
string
{
h
:=
getHandler
(
op
)
if
h
==
nil
{
return
"unknown"
}
return
h
.
Name
}
func
getHandler
(
o
uint32
)
*
operationHandler
{
if
o
>=
_OPCODE_COUNT
{
return
nil
}
return
operationHandlers
[
o
]
}
var
maxInputSize
uintptr
func
init
()
{
operationHandlers
=
make
([]
*
operationHandler
,
_OPCODE_COUNT
)
for
i
:=
range
operationHandlers
{
operationHandlers
[
i
]
=
&
operationHandler
{
Name
:
fmt
.
Sprintf
(
"OPCODE-%d"
,
i
)}
}
fileOps
:=
[]
uint32
{
_OP_READLINK
,
_OP_NOTIFY_INVAL_ENTRY
,
_OP_NOTIFY_DELETE
}
for
_
,
op
:=
range
fileOps
{
operationHandlers
[
op
]
.
FileNameOut
=
true
}
maxInputSize
=
0
for
op
,
sz
:=
range
map
[
uint32
]
uintptr
{
_OP_FORGET
:
unsafe
.
Sizeof
(
ForgetIn
{}),
_OP_BATCH_FORGET
:
unsafe
.
Sizeof
(
_BatchForgetIn
{}),
_OP_GETATTR
:
unsafe
.
Sizeof
(
GetAttrIn
{}),
_OP_SETATTR
:
unsafe
.
Sizeof
(
SetAttrIn
{}),
_OP_MKNOD
:
unsafe
.
Sizeof
(
MknodIn
{}),
_OP_MKDIR
:
unsafe
.
Sizeof
(
MkdirIn
{}),
_OP_RENAME
:
unsafe
.
Sizeof
(
Rename1In
{}),
_OP_LINK
:
unsafe
.
Sizeof
(
LinkIn
{}),
_OP_OPEN
:
unsafe
.
Sizeof
(
OpenIn
{}),
_OP_READ
:
unsafe
.
Sizeof
(
ReadIn
{}),
_OP_WRITE
:
unsafe
.
Sizeof
(
WriteIn
{}),
_OP_RELEASE
:
unsafe
.
Sizeof
(
ReleaseIn
{}),
_OP_FSYNC
:
unsafe
.
Sizeof
(
FsyncIn
{}),
_OP_SETXATTR
:
unsafe
.
Sizeof
(
SetXAttrIn
{}),
_OP_GETXATTR
:
unsafe
.
Sizeof
(
GetXAttrIn
{}),
_OP_LISTXATTR
:
unsafe
.
Sizeof
(
GetXAttrIn
{}),
_OP_FLUSH
:
unsafe
.
Sizeof
(
FlushIn
{}),
_OP_INIT
:
unsafe
.
Sizeof
(
InitIn
{}),
_OP_OPENDIR
:
unsafe
.
Sizeof
(
OpenIn
{}),
_OP_READDIR
:
unsafe
.
Sizeof
(
ReadIn
{}),
_OP_RELEASEDIR
:
unsafe
.
Sizeof
(
ReleaseIn
{}),
_OP_FSYNCDIR
:
unsafe
.
Sizeof
(
FsyncIn
{}),
_OP_GETLK
:
unsafe
.
Sizeof
(
LkIn
{}),
_OP_SETLK
:
unsafe
.
Sizeof
(
LkIn
{}),
_OP_SETLKW
:
unsafe
.
Sizeof
(
LkIn
{}),
_OP_ACCESS
:
unsafe
.
Sizeof
(
AccessIn
{}),
_OP_CREATE
:
unsafe
.
Sizeof
(
CreateIn
{}),
_OP_INTERRUPT
:
unsafe
.
Sizeof
(
InterruptIn
{}),
_OP_BMAP
:
unsafe
.
Sizeof
(
_BmapIn
{}),
_OP_IOCTL
:
unsafe
.
Sizeof
(
_IoctlIn
{}),
_OP_POLL
:
unsafe
.
Sizeof
(
_PollIn
{}),
_OP_NOTIFY_REPLY
:
unsafe
.
Sizeof
(
NotifyRetrieveIn
{}),
_OP_FALLOCATE
:
unsafe
.
Sizeof
(
FallocateIn
{}),
_OP_READDIRPLUS
:
unsafe
.
Sizeof
(
ReadIn
{}),
_OP_RENAME2
:
unsafe
.
Sizeof
(
RenameIn
{}),
_OP_LSEEK
:
unsafe
.
Sizeof
(
LseekIn
{}),
_OP_COPY_FILE_RANGE
:
unsafe
.
Sizeof
(
CopyFileRangeIn
{}),
}
{
operationHandlers
[
op
]
.
InputSize
=
sz
if
sz
>
maxInputSize
{
maxInputSize
=
sz
}
}
for
op
,
sz
:=
range
map
[
uint32
]
uintptr
{
_OP_LOOKUP
:
unsafe
.
Sizeof
(
EntryOut
{}),
_OP_GETATTR
:
unsafe
.
Sizeof
(
AttrOut
{}),
_OP_SETATTR
:
unsafe
.
Sizeof
(
AttrOut
{}),
_OP_SYMLINK
:
unsafe
.
Sizeof
(
EntryOut
{}),
_OP_MKNOD
:
unsafe
.
Sizeof
(
EntryOut
{}),
_OP_MKDIR
:
unsafe
.
Sizeof
(
EntryOut
{}),
_OP_LINK
:
unsafe
.
Sizeof
(
EntryOut
{}),
_OP_OPEN
:
unsafe
.
Sizeof
(
OpenOut
{}),
_OP_WRITE
:
unsafe
.
Sizeof
(
WriteOut
{}),
_OP_STATFS
:
unsafe
.
Sizeof
(
StatfsOut
{}),
_OP_GETXATTR
:
unsafe
.
Sizeof
(
GetXAttrOut
{}),
_OP_LISTXATTR
:
unsafe
.
Sizeof
(
GetXAttrOut
{}),
_OP_INIT
:
unsafe
.
Sizeof
(
InitOut
{}),
_OP_OPENDIR
:
unsafe
.
Sizeof
(
OpenOut
{}),
_OP_GETLK
:
unsafe
.
Sizeof
(
LkOut
{}),
_OP_CREATE
:
unsafe
.
Sizeof
(
CreateOut
{}),
_OP_BMAP
:
unsafe
.
Sizeof
(
_BmapOut
{}),
_OP_IOCTL
:
unsafe
.
Sizeof
(
_IoctlOut
{}),
_OP_POLL
:
unsafe
.
Sizeof
(
_PollOut
{}),
_OP_NOTIFY_INVAL_ENTRY
:
unsafe
.
Sizeof
(
NotifyInvalEntryOut
{}),
_OP_NOTIFY_INVAL_INODE
:
unsafe
.
Sizeof
(
NotifyInvalInodeOut
{}),
_OP_NOTIFY_STORE_CACHE
:
unsafe
.
Sizeof
(
NotifyStoreOut
{}),
_OP_NOTIFY_RETRIEVE_CACHE
:
unsafe
.
Sizeof
(
NotifyRetrieveOut
{}),
_OP_NOTIFY_DELETE
:
unsafe
.
Sizeof
(
NotifyInvalDeleteOut
{}),
_OP_LSEEK
:
unsafe
.
Sizeof
(
LseekOut
{}),
_OP_COPY_FILE_RANGE
:
unsafe
.
Sizeof
(
WriteOut
{}),
}
{
operationHandlers
[
op
]
.
OutputSize
=
sz
}
for
op
,
v
:=
range
map
[
uint32
]
string
{
_OP_LOOKUP
:
"LOOKUP"
,
_OP_FORGET
:
"FORGET"
,
_OP_BATCH_FORGET
:
"BATCH_FORGET"
,
_OP_GETATTR
:
"GETATTR"
,
_OP_SETATTR
:
"SETATTR"
,
_OP_READLINK
:
"READLINK"
,
_OP_SYMLINK
:
"SYMLINK"
,
_OP_MKNOD
:
"MKNOD"
,
_OP_MKDIR
:
"MKDIR"
,
_OP_UNLINK
:
"UNLINK"
,
_OP_RMDIR
:
"RMDIR"
,
_OP_RENAME
:
"RENAME"
,
_OP_LINK
:
"LINK"
,
_OP_OPEN
:
"OPEN"
,
_OP_READ
:
"READ"
,
_OP_WRITE
:
"WRITE"
,
_OP_STATFS
:
"STATFS"
,
_OP_RELEASE
:
"RELEASE"
,
_OP_FSYNC
:
"FSYNC"
,
_OP_SETXATTR
:
"SETXATTR"
,
_OP_GETXATTR
:
"GETXATTR"
,
_OP_LISTXATTR
:
"LISTXATTR"
,
_OP_REMOVEXATTR
:
"REMOVEXATTR"
,
_OP_FLUSH
:
"FLUSH"
,
_OP_INIT
:
"INIT"
,
_OP_OPENDIR
:
"OPENDIR"
,
_OP_READDIR
:
"READDIR"
,
_OP_RELEASEDIR
:
"RELEASEDIR"
,
_OP_FSYNCDIR
:
"FSYNCDIR"
,
_OP_GETLK
:
"GETLK"
,
_OP_SETLK
:
"SETLK"
,
_OP_SETLKW
:
"SETLKW"
,
_OP_ACCESS
:
"ACCESS"
,
_OP_CREATE
:
"CREATE"
,
_OP_INTERRUPT
:
"INTERRUPT"
,
_OP_BMAP
:
"BMAP"
,
_OP_DESTROY
:
"DESTROY"
,
_OP_IOCTL
:
"IOCTL"
,
_OP_POLL
:
"POLL"
,
_OP_NOTIFY_REPLY
:
"NOTIFY_REPLY"
,
_OP_NOTIFY_INVAL_ENTRY
:
"NOTIFY_INVAL_ENTRY"
,
_OP_NOTIFY_INVAL_INODE
:
"NOTIFY_INVAL_INODE"
,
_OP_NOTIFY_STORE_CACHE
:
"NOTIFY_STORE"
,
_OP_NOTIFY_RETRIEVE_CACHE
:
"NOTIFY_RETRIEVE"
,
_OP_NOTIFY_DELETE
:
"NOTIFY_DELETE"
,
_OP_FALLOCATE
:
"FALLOCATE"
,
_OP_READDIRPLUS
:
"READDIRPLUS"
,
_OP_RENAME2
:
"RENAME2"
,
_OP_LSEEK
:
"LSEEK"
,
_OP_COPY_FILE_RANGE
:
"COPY_FILE_RANGE"
,
}
{
operationHandlers
[
op
]
.
Name
=
v
}
for
op
,
v
:=
range
map
[
uint32
]
operationFunc
{
_OP_OPEN
:
doOpen
,
_OP_READDIR
:
doReadDir
,
_OP_WRITE
:
doWrite
,
_OP_OPENDIR
:
doOpenDir
,
_OP_CREATE
:
doCreate
,
_OP_SETATTR
:
doSetattr
,
_OP_GETXATTR
:
doGetXAttr
,
_OP_LISTXATTR
:
doGetXAttr
,
_OP_GETATTR
:
doGetAttr
,
_OP_FORGET
:
doForget
,
_OP_BATCH_FORGET
:
doBatchForget
,
_OP_READLINK
:
doReadlink
,
_OP_INIT
:
doInit
,
_OP_LOOKUP
:
doLookup
,
_OP_MKNOD
:
doMknod
,
_OP_MKDIR
:
doMkdir
,
_OP_UNLINK
:
doUnlink
,
_OP_RMDIR
:
doRmdir
,
_OP_LINK
:
doLink
,
_OP_READ
:
doRead
,
_OP_FLUSH
:
doFlush
,
_OP_RELEASE
:
doRelease
,
_OP_FSYNC
:
doFsync
,
_OP_RELEASEDIR
:
doReleaseDir
,
_OP_FSYNCDIR
:
doFsyncDir
,
_OP_SETXATTR
:
doSetXAttr
,
_OP_REMOVEXATTR
:
doRemoveXAttr
,
_OP_GETLK
:
doGetLk
,
_OP_SETLK
:
doSetLk
,
_OP_SETLKW
:
doSetLkw
,
_OP_ACCESS
:
doAccess
,
_OP_SYMLINK
:
doSymlink
,
_OP_RENAME
:
doRename
,
_OP_STATFS
:
doStatFs
,
_OP_IOCTL
:
doIoctl
,
_OP_DESTROY
:
doDestroy
,
_OP_NOTIFY_REPLY
:
doNotifyReply
,
_OP_FALLOCATE
:
doFallocate
,
_OP_READDIRPLUS
:
doReadDirPlus
,
_OP_RENAME2
:
doRename2
,
_OP_INTERRUPT
:
doInterrupt
,
_OP_COPY_FILE_RANGE
:
doCopyFileRange
,
_OP_LSEEK
:
doLseek
,
}
{
operationHandlers
[
op
]
.
Func
=
v
}
// Outputs.
for
op
,
f
:=
range
map
[
uint32
]
castPointerFunc
{
_OP_LOOKUP
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
EntryOut
)(
ptr
)
},
_OP_OPEN
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
OpenOut
)(
ptr
)
},
_OP_OPENDIR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
OpenOut
)(
ptr
)
},
_OP_GETATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
AttrOut
)(
ptr
)
},
_OP_CREATE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
CreateOut
)(
ptr
)
},
_OP_LINK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
EntryOut
)(
ptr
)
},
_OP_SETATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
AttrOut
)(
ptr
)
},
_OP_INIT
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
InitOut
)(
ptr
)
},
_OP_MKDIR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
EntryOut
)(
ptr
)
},
_OP_NOTIFY_INVAL_ENTRY
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyInvalEntryOut
)(
ptr
)
},
_OP_NOTIFY_INVAL_INODE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyInvalInodeOut
)(
ptr
)
},
_OP_NOTIFY_STORE_CACHE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyStoreOut
)(
ptr
)
},
_OP_NOTIFY_RETRIEVE_CACHE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyRetrieveOut
)(
ptr
)
},
_OP_NOTIFY_DELETE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyInvalDeleteOut
)(
ptr
)
},
_OP_STATFS
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
StatfsOut
)(
ptr
)
},
_OP_SYMLINK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
EntryOut
)(
ptr
)
},
_OP_GETLK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LkOut
)(
ptr
)
},
_OP_LSEEK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LseekOut
)(
ptr
)
},
_OP_COPY_FILE_RANGE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
WriteOut
)(
ptr
)
},
}
{
operationHandlers
[
op
]
.
DecodeOut
=
f
}
// Inputs.
for
op
,
f
:=
range
map
[
uint32
]
castPointerFunc
{
_OP_FLUSH
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
FlushIn
)(
ptr
)
},
_OP_GETATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
GetAttrIn
)(
ptr
)
},
_OP_SETXATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
SetXAttrIn
)(
ptr
)
},
_OP_GETXATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
GetXAttrIn
)(
ptr
)
},
_OP_LISTXATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
GetXAttrIn
)(
ptr
)
},
_OP_SETATTR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
SetAttrIn
)(
ptr
)
},
_OP_INIT
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
InitIn
)(
ptr
)
},
_OP_IOCTL
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
_IoctlIn
)(
ptr
)
},
_OP_OPEN
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
OpenIn
)(
ptr
)
},
_OP_MKNOD
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
MknodIn
)(
ptr
)
},
_OP_CREATE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
CreateIn
)(
ptr
)
},
_OP_READ
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ReadIn
)(
ptr
)
},
_OP_WRITE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
WriteIn
)(
ptr
)
},
_OP_READDIR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ReadIn
)(
ptr
)
},
_OP_ACCESS
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
AccessIn
)(
ptr
)
},
_OP_FORGET
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ForgetIn
)(
ptr
)
},
_OP_BATCH_FORGET
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
_BatchForgetIn
)(
ptr
)
},
_OP_LINK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LinkIn
)(
ptr
)
},
_OP_MKDIR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
MkdirIn
)(
ptr
)
},
_OP_RELEASE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ReleaseIn
)(
ptr
)
},
_OP_RELEASEDIR
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ReleaseIn
)(
ptr
)
},
_OP_FALLOCATE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
FallocateIn
)(
ptr
)
},
_OP_NOTIFY_REPLY
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
NotifyRetrieveIn
)(
ptr
)
},
_OP_READDIRPLUS
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
ReadIn
)(
ptr
)
},
_OP_RENAME
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
Rename1In
)(
ptr
)
},
_OP_GETLK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LkIn
)(
ptr
)
},
_OP_SETLK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LkIn
)(
ptr
)
},
_OP_SETLKW
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LkIn
)(
ptr
)
},
_OP_RENAME2
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
RenameIn
)(
ptr
)
},
_OP_INTERRUPT
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
InterruptIn
)(
ptr
)
},
_OP_LSEEK
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
LseekIn
)(
ptr
)
},
_OP_COPY_FILE_RANGE
:
func
(
ptr
unsafe
.
Pointer
)
interface
{}
{
return
(
*
CopyFileRangeIn
)(
ptr
)
},
}
{
operationHandlers
[
op
]
.
DecodeIn
=
f
}
// File name args.
for
op
,
count
:=
range
map
[
uint32
]
int
{
_OP_CREATE
:
1
,
_OP_SETXATTR
:
1
,
_OP_GETXATTR
:
1
,
_OP_LINK
:
1
,
_OP_LOOKUP
:
1
,
_OP_MKDIR
:
1
,
_OP_MKNOD
:
1
,
_OP_REMOVEXATTR
:
1
,
_OP_RENAME
:
2
,
_OP_RENAME2
:
2
,
_OP_RMDIR
:
1
,
_OP_SYMLINK
:
2
,
_OP_UNLINK
:
1
,
}
{
operationHandlers
[
op
]
.
FileNames
=
count
}
var
r
request
sizeOfOutHeader
:=
unsafe
.
Sizeof
(
OutHeader
{})
for
code
,
h
:=
range
operationHandlers
{
if
h
.
OutputSize
+
sizeOfOutHeader
>
unsafe
.
Sizeof
(
r
.
outBuf
)
{
log
.
Panicf
(
"request output buffer too small: code %v, sz %d + %d %v"
,
code
,
h
.
OutputSize
,
sizeOfOutHeader
,
h
)
}
}
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll.go
deleted
100644 → 0
View file @
e3e61d67
package
fuse
// Go 1.9 introduces polling for file I/O. The implementation causes
// the runtime's epoll to take up the last GOMAXPROCS slot, and if
// that happens, we won't have any threads left to service FUSE's
// _OP_POLL request. Prevent this by forcing _OP_POLL to happen, so we
// can say ENOSYS and prevent further _OP_POLL requests.
const
pollHackName
=
".go-fuse-epoll-hack"
const
pollHackInode
=
^
uint64
(
0
)
func
doPollHackLookup
(
ms
*
Server
,
req
*
request
)
{
attr
:=
Attr
{
Ino
:
pollHackInode
,
Mode
:
S_IFREG
|
0644
,
Nlink
:
1
,
}
switch
req
.
inHeader
.
Opcode
{
case
_OP_LOOKUP
:
out
:=
(
*
EntryOut
)(
req
.
outData
())
*
out
=
EntryOut
{
NodeId
:
pollHackInode
,
Attr
:
attr
,
}
req
.
status
=
OK
case
_OP_OPEN
:
out
:=
(
*
OpenOut
)(
req
.
outData
())
*
out
=
OpenOut
{
Fh
:
pollHackInode
,
}
req
.
status
=
OK
case
_OP_GETATTR
:
out
:=
(
*
AttrOut
)(
req
.
outData
())
out
.
Attr
=
attr
req
.
status
=
OK
case
_OP_POLL
:
req
.
status
=
ENOSYS
default
:
// We want to avoid switching off features through our
// poll hack, so don't use ENOSYS
req
.
status
=
ERANGE
}
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_darwin.go
deleted
100644 → 0
View file @
e3e61d67
package
fuse
import
(
"path/filepath"
"syscall"
"unsafe"
)
type
pollFd
struct
{
Fd
int32
Events
int16
Revents
int16
}
func
sysPoll
(
fds
[]
pollFd
,
timeout
int
)
(
n
int
,
err
error
)
{
r0
,
_
,
e1
:=
syscall
.
Syscall
(
syscall
.
SYS_POLL
,
uintptr
(
unsafe
.
Pointer
(
&
fds
[
0
])),
uintptr
(
len
(
fds
)),
uintptr
(
timeout
))
n
=
int
(
r0
)
if
e1
!=
0
{
err
=
syscall
.
Errno
(
e1
)
}
return
n
,
err
}
func
pollHack
(
mountPoint
string
)
error
{
const
(
POLLIN
=
0x1
POLLPRI
=
0x2
POLLOUT
=
0x4
POLLRDHUP
=
0x2000
POLLERR
=
0x8
POLLHUP
=
0x10
)
fd
,
err
:=
syscall
.
Open
(
filepath
.
Join
(
mountPoint
,
pollHackName
),
syscall
.
O_CREAT
|
syscall
.
O_TRUNC
|
syscall
.
O_RDWR
,
0644
)
if
err
!=
nil
{
return
err
}
pollData
:=
[]
pollFd
{{
Fd
:
int32
(
fd
),
Events
:
POLLIN
|
POLLPRI
|
POLLOUT
,
}}
// Trigger _OP_POLL, so we can say ENOSYS. We don't care about
// the return value.
sysPoll
(
pollData
,
0
)
syscall
.
Close
(
fd
)
return
nil
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/poll_linux.go
deleted
100644 → 0
View file @
e3e61d67
package
fuse
import
(
"path/filepath"
"syscall"
"golang.org/x/sys/unix"
)
func
pollHack
(
mountPoint
string
)
error
{
fd
,
err
:=
syscall
.
Open
(
filepath
.
Join
(
mountPoint
,
pollHackName
),
syscall
.
O_RDONLY
,
0
)
if
err
!=
nil
{
return
err
}
pollData
:=
[]
unix
.
PollFd
{{
Fd
:
int32
(
fd
),
Events
:
unix
.
POLLIN
|
unix
.
POLLPRI
|
unix
.
POLLOUT
,
}}
// Trigger _OP_POLL, so we can say ENOSYS. We don't care about
// the return value.
unix
.
Poll
(
pollData
,
0
)
syscall
.
Close
(
fd
)
return
nil
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
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"
,
CAP_PARALLEL_DIROPS
:
"PARALLEL_DIROPS"
,
CAP_POSIX_ACL
:
"POSIX_ACL"
,
CAP_HANDLE_KILLPRIV
:
"HANDLE_KILLPRIV"
,
CAP_ABORT_ERROR
:
"ABORT_ERROR"
,
CAP_MAX_PAGES
:
"MAX_PAGES"
,
CAP_CACHE_SYMLINKS
:
"CACHE_SYMLINKS"
,
CAP_NO_OPENDIR_SUPPORT
:
"NO_OPENDIR_SUPPORT"
,
CAP_EXPLICIT_INVAL_DATA
:
"EXPLICIT_INVAL_DATA"
,
}
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"
,
FOPEN_CACHE_DIR
:
"CACHE_DIR"
,
FOPEN_STREAM
:
"STREAM"
,
}
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
(
in
*
ForgetIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Nlookup=%d}"
,
in
.
Nlookup
)
}
func
(
in
*
_BatchForgetIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Count=%d}"
,
in
.
Count
)
}
func
(
in
*
MkdirIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{0%o (0%o)}"
,
in
.
Mode
,
in
.
Umask
)
}
func
(
in
*
Rename1In
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d}"
,
in
.
Newdir
)
}
func
(
in
*
RenameIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d %x}"
,
in
.
Newdir
,
in
.
Flags
)
}
func
(
in
*
SetAttrIn
)
string
()
string
{
s
:=
[]
string
{}
if
in
.
Valid
&
FATTR_MODE
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"mode 0%o"
,
in
.
Mode
))
}
if
in
.
Valid
&
FATTR_UID
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"uid %d"
,
in
.
Uid
))
}
if
in
.
Valid
&
FATTR_GID
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"gid %d"
,
in
.
Gid
))
}
if
in
.
Valid
&
FATTR_SIZE
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"size %d"
,
in
.
Size
))
}
if
in
.
Valid
&
FATTR_ATIME
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"atime %d.%09d"
,
in
.
Atime
,
in
.
Atimensec
))
}
if
in
.
Valid
&
FATTR_MTIME
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"mtime %d.%09d"
,
in
.
Mtime
,
in
.
Mtimensec
))
}
if
in
.
Valid
&
FATTR_FH
!=
0
{
s
=
append
(
s
,
fmt
.
Sprintf
(
"fh %d"
,
in
.
Fh
))
}
// TODO - FATTR_ATIME_NOW = (1 << 7), FATTR_MTIME_NOW = (1 << 8), FATTR_LOCKOWNER = (1 << 9)
return
fmt
.
Sprintf
(
"{%s}"
,
strings
.
Join
(
s
,
", "
))
}
func
(
in
*
ReleaseIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d %s %s L%d}"
,
in
.
Fh
,
flagString
(
openFlagNames
,
int64
(
in
.
Flags
),
""
),
flagString
(
releaseFlagNames
,
int64
(
in
.
ReleaseFlags
),
""
),
in
.
LockOwner
)
}
func
(
in
*
OpenIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{%s}"
,
flagString
(
openFlagNames
,
int64
(
in
.
Flags
),
"O_RDONLY"
))
}
func
(
in
*
OpenOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d %s}"
,
in
.
Fh
,
flagString
(
fuseOpenFlagNames
,
int64
(
in
.
OpenFlags
),
""
))
}
func
(
in
*
InitIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{%d.%d Ra 0x%x %s}"
,
in
.
Major
,
in
.
Minor
,
in
.
MaxReadAhead
,
flagString
(
initFlagNames
,
int64
(
in
.
Flags
),
""
))
}
func
(
o
*
InitOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{%d.%d Ra 0x%x %s %d/%d Wr 0x%x Tg 0x%x}"
,
o
.
Major
,
o
.
Minor
,
o
.
MaxReadAhead
,
flagString
(
initFlagNames
,
int64
(
o
.
Flags
),
""
),
o
.
CongestionThreshold
,
o
.
MaxBackground
,
o
.
MaxWrite
,
o
.
TimeGran
)
}
func
(
s
*
FsyncIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d Flags %x}"
,
s
.
Fh
,
s
.
FsyncFlags
)
}
func
(
in
*
SetXAttrIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{sz %d f%o}"
,
in
.
Size
,
in
.
Flags
)
}
func
(
in
*
GetXAttrIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{sz %d}"
,
in
.
Size
)
}
func
(
o
*
GetXAttrOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{sz %d}"
,
o
.
Size
)
}
func
(
in
*
AccessIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{u=%d g=%d %s}"
,
in
.
Uid
,
in
.
Gid
,
flagString
(
accessFlagName
,
int64
(
in
.
Mask
),
""
))
}
func
(
in
*
FlushIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d}"
,
in
.
Fh
)
}
func
(
o
*
AttrOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{tA=%gs %v}"
,
ft
(
o
.
AttrValid
,
o
.
AttrValidNsec
),
&
o
.
Attr
)
}
// ft converts (seconds , nanoseconds) -> float(seconds)
func
ft
(
tsec
uint64
,
tnsec
uint32
)
float64
{
return
float64
(
tsec
)
+
float64
(
tnsec
)
*
1E-9
}
// Returned by LOOKUP
func
(
o
*
EntryOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d g%d tE=%gs tA=%gs %v}"
,
o
.
NodeId
,
o
.
Generation
,
ft
(
o
.
EntryValid
,
o
.
EntryValidNsec
),
ft
(
o
.
AttrValid
,
o
.
AttrValidNsec
),
&
o
.
Attr
)
}
func
(
o
*
CreateOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d g%d %v %v}"
,
o
.
NodeId
,
o
.
Generation
,
&
o
.
EntryOut
,
&
o
.
OpenOut
)
}
func
(
o
*
StatfsOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{blocks (%d,%d)/%d files %d/%d bs%d nl%d frs%d}"
,
o
.
Bfree
,
o
.
Bavail
,
o
.
Blocks
,
o
.
Ffree
,
o
.
Files
,
o
.
Bsize
,
o
.
NameLen
,
o
.
Frsize
)
}
func
(
o
*
NotifyInvalEntryOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{parent i%d sz %d}"
,
o
.
Parent
,
o
.
NameLen
)
}
func
(
o
*
NotifyInvalInodeOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d [%d +%d)}"
,
o
.
Ino
,
o
.
Off
,
o
.
Length
)
}
func
(
o
*
NotifyInvalDeleteOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{parent i%d ch i%d sz %d}"
,
o
.
Parent
,
o
.
Child
,
o
.
NameLen
)
}
func
(
o
*
NotifyStoreOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{i%d [%d +%d)}"
,
o
.
Nodeid
,
o
.
Offset
,
o
.
Size
)
}
func
(
o
*
NotifyRetrieveOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{> %d: i%d [%d +%d)}"
,
o
.
NotifyUnique
,
o
.
Nodeid
,
o
.
Offset
,
o
.
Size
)
}
func
(
i
*
NotifyRetrieveIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{[%d +%d)}"
,
i
.
Offset
,
i
.
Size
)
}
func
(
f
*
FallocateIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%d +%d) mod 0%o}"
,
f
.
Fh
,
f
.
Offset
,
f
.
Length
,
f
.
Mode
)
}
func
(
f
*
LinkIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Oldnodeid: %d}"
,
f
.
Oldnodeid
)
}
func
(
o
*
WriteOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{%db }"
,
o
.
Size
)
}
func
(
i
*
CopyFileRangeIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%d +%d) => i%d Fh %d [%d, %d)}"
,
i
.
FhIn
,
i
.
OffIn
,
i
.
Len
,
i
.
NodeIdOut
,
i
.
FhOut
,
i
.
OffOut
,
i
.
Len
)
}
func
(
in
*
InterruptIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{ix %d}"
,
in
.
Unique
)
}
var
seekNames
=
map
[
uint32
]
string
{
0
:
"SET"
,
1
:
"CUR"
,
2
:
"END"
,
3
:
"DATA"
,
4
:
"HOLE"
,
}
func
(
in
*
LseekIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%s +%d)}"
,
in
.
Fh
,
seekNames
[
in
.
Whence
],
in
.
Offset
)
}
func
(
o
*
LseekOut
)
string
()
string
{
return
fmt
.
Sprintf
(
"{%d}"
,
o
.
Offset
)
}
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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 %f "
+
"M %f "
+
"C %f}"
,
a
.
Mode
,
a
.
Size
,
a
.
Nlink
,
a
.
Uid
,
a
.
Gid
,
a
.
Blocks
,
a
.
Rdev
,
a
.
Ino
,
ft
(
a
.
Atime
,
a
.
Atimensec
),
ft
(
a
.
Mtime
,
a
.
Mtimensec
),
ft
(
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 [%d +%d) %s}"
,
me
.
Fh
,
me
.
Offset
,
me
.
Size
,
flagString
(
readFlagNames
,
int64
(
me
.
ReadFlags
),
""
))
}
func
(
me
*
WriteIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%d +%d) %s}"
,
me
.
Fh
,
me
.
Offset
,
me
.
Size
,
flagString
(
writeFlagNames
,
int64
(
me
.
WriteFlags
),
""
))
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/print_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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 %f "
+
"M %f "
+
"C %f}"
,
a
.
Mode
,
a
.
Size
,
a
.
Nlink
,
a
.
Uid
,
a
.
Gid
,
a
.
Blocks
,
a
.
Blksize
,
a
.
Rdev
,
a
.
Ino
,
ft
(
a
.
Atime
,
a
.
Atimensec
),
ft
(
a
.
Mtime
,
a
.
Mtimensec
),
ft
(
a
.
Ctime
,
a
.
Ctimensec
))
}
func
(
in
*
CreateIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{0%o [%s] (0%o)}"
,
in
.
Mode
,
flagString
(
openFlagNames
,
int64
(
in
.
Flags
),
"O_RDONLY"
),
in
.
Umask
)
}
func
(
in
*
GetAttrIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d}"
,
in
.
Fh_
)
}
func
(
in
*
MknodIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{0%o (0%o), %d}"
,
in
.
Mode
,
in
.
Umask
,
in
.
Rdev
)
}
func
(
in
*
ReadIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%d +%d) %s L %d %s}"
,
in
.
Fh
,
in
.
Offset
,
in
.
Size
,
flagString
(
readFlagNames
,
int64
(
in
.
ReadFlags
),
""
),
in
.
LockOwner
,
flagString
(
openFlagNames
,
int64
(
in
.
Flags
),
"RDONLY"
))
}
func
(
in
*
WriteIn
)
string
()
string
{
return
fmt
.
Sprintf
(
"{Fh %d [%d +%d) %s L %d %s}"
,
in
.
Fh
,
in
.
Offset
,
in
.
Size
,
flagString
(
writeFlagNames
,
int64
(
in
.
WriteFlags
),
""
),
in
.
LockOwner
,
flagString
(
openFlagNames
,
int64
(
in
.
Flags
),
"RDONLY"
))
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/read.go
deleted
100644 → 0
View file @
e3e61d67
// 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
()
{
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request.go
deleted
100644 → 0
View file @
e3e61d67
// 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
{
inflightIndex
int
cancel
chan
struct
{}
// written under Server.reqMu
interrupted
bool
inputBuf
[]
byte
// These split up inputBuf.
inHeader
*
InHeader
// generic header
inData
unsafe
.
Pointer
// per op data
arg
[]
byte
// flat data.
filenames
[]
string
// filename arguments
// Output data.
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
}
func
(
r
*
request
)
clear
()
{
r
.
inputBuf
=
nil
r
.
inHeader
=
nil
r
.
inData
=
nil
r
.
arg
=
nil
r
.
filenames
=
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
!=
nil
&&
r
.
handler
.
DecodeIn
!=
nil
{
val
=
fmt
.
Sprintf
(
"%v "
,
Print
(
r
.
handler
.
DecodeIn
(
r
.
inData
)))
}
names
:=
""
if
r
.
filenames
!=
nil
{
names
=
fmt
.
Sprintf
(
"%q"
,
r
.
filenames
)
}
if
l
:=
len
(
r
.
arg
);
l
>
0
{
data
:=
""
if
len
(
r
.
filenames
)
==
0
{
dots
:=
""
if
l
>
8
{
l
=
8
dots
=
"..."
}
data
=
fmt
.
Sprintf
(
"%q%s"
,
r
.
arg
[
:
l
],
dots
)
}
names
+=
fmt
.
Sprintf
(
"%s %db"
,
data
,
len
(
r
.
arg
))
}
return
fmt
.
Sprintf
(
"rx %d: %s i%d %s%s"
,
r
.
inHeader
.
Unique
,
operationName
(
r
.
inHeader
.
Opcode
),
r
.
inHeader
.
NodeId
,
val
,
names
)
}
func
(
r
*
request
)
OutputDebug
()
string
{
var
dataStr
string
if
r
.
handler
!=
nil
&&
r
.
handler
.
DecodeOut
!=
nil
&&
r
.
handler
.
OutputSize
>
0
{
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
!=
nil
&&
r
.
handler
.
FileNameOut
{
s
:=
strings
.
TrimRight
(
string
(
r
.
flatData
),
"
\x00
"
)
flatStr
=
fmt
.
Sprintf
(
" %q"
,
s
)
}
else
{
spl
:=
""
if
r
.
fdData
!=
nil
{
spl
=
" (fd data)"
}
else
{
l
:=
len
(
r
.
flatData
)
s
:=
""
if
l
>
8
{
l
=
8
s
=
"..."
}
spl
=
fmt
.
Sprintf
(
" %q%s"
,
r
.
flatData
[
:
l
],
s
)
}
flatStr
=
fmt
.
Sprintf
(
" %db data%s"
,
r
.
flatDataSize
(),
spl
)
}
}
extraStr
:=
dataStr
+
flatStr
if
extraStr
!=
""
{
extraStr
=
", "
+
extraStr
}
return
fmt
.
Sprintf
(
"tx %d: %v%s"
,
r
.
inHeader
.
Unique
,
r
.
status
,
extraStr
)
}
// 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
)
parseHeader
()
Status
{
if
len
(
r
.
inputBuf
)
<
int
(
unsafe
.
Sizeof
(
InHeader
{}))
{
log
.
Printf
(
"Short read for input header: %v"
,
r
.
inputBuf
)
return
EINVAL
}
r
.
inHeader
=
(
*
InHeader
)(
unsafe
.
Pointer
(
&
r
.
inputBuf
[
0
]))
return
OK
}
func
(
r
*
request
)
parse
()
{
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
[
unsafe
.
Sizeof
(
InHeader
{})
:
]
}
count
:=
r
.
handler
.
FileNames
if
count
>
0
{
if
count
==
1
&&
r
.
inHeader
.
Opcode
==
_OP_SETXATTR
{
// SETXATTR is special: the only opcode with a file name AND a
// binary argument.
splits
:=
bytes
.
SplitN
(
r
.
arg
,
[]
byte
{
0
},
2
)
r
.
filenames
=
[]
string
{
string
(
splits
[
0
])}
}
else
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
])
}
func
(
r
*
request
)
outData
()
unsafe
.
Pointer
{
return
unsafe
.
Pointer
(
&
r
.
outBuf
[
sizeOfOutHeader
])
}
// serializeHeader serializes the response header. The header points
// to an internal buffer of the receiver.
func
(
r
*
request
)
serializeHeader
(
flatDataSize
int
)
(
header
[]
byte
)
{
var
dataLength
uintptr
if
r
.
handler
!=
nil
{
dataLength
=
r
.
handler
.
OutputSize
}
if
r
.
status
>
OK
{
// only do this for positive status; negative status
// is used for notification.
dataLength
=
0
}
// [GET|LIST]XATTR is two opcodes in one: get/list xattr size (return
// structured GetXAttrOut, no flat data) and get/list xattr data
// (return no structured data, but only flat data)
if
r
.
inHeader
.
Opcode
==
_OP_GETXATTR
||
r
.
inHeader
.
Opcode
==
_OP_LISTXATTR
{
if
(
*
GetXAttrIn
)(
r
.
inData
)
.
Size
!=
0
{
dataLength
=
0
}
}
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
)
+
flatDataSize
)
return
header
}
func
(
r
*
request
)
flatDataSize
()
int
{
if
r
.
fdData
!=
nil
{
return
r
.
fdData
.
Size
()
}
return
len
(
r
.
flatData
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/request_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
=
28
)
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"log"
"math"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"syscall"
"time"
"unsafe"
)
const
(
// The kernel caps writes at 128k.
MAX_KERNEL_WRITE
=
128
*
1024
)
// Server contains the logic for reading from the FUSE device and
// translating it to RawFileSystem interface calls.
type
Server
struct
{
// Empty if unmounted.
mountPoint
string
fileSystem
RawFileSystem
// writeMu serializes close and notify writes
writeMu
sync
.
Mutex
// I/O with kernel and daemon.
mountFd
int
latencies
LatencyMap
opts
*
MountOptions
// Pools for []byte
buffers
bufferPool
// Pool for request structs.
reqPool
sync
.
Pool
// Pool for raw requests data
readPool
sync
.
Pool
reqMu
sync
.
Mutex
reqReaders
int
reqInflight
[]
*
request
kernelSettings
InitIn
// in-flight notify-retrieve queries
retrieveMu
sync
.
Mutex
retrieveNext
uint64
retrieveTab
map
[
uint64
]
*
retrieveCacheRequest
// notifyUnique -> retrieve request
singleReader
bool
canSplice
bool
loops
sync
.
WaitGroup
ready
chan
error
// for implementing single threaded processing.
requestProcessingMu
sync
.
Mutex
}
// SetDebug is deprecated. Use MountOptions.Debug instead.
func
(
ms
*
Server
)
SetDebug
(
dbg
bool
)
{
// This will typically trigger the race detector.
ms
.
opts
.
Debug
=
dbg
}
// KernelSettings returns the Init message from the kernel, so
// filesystems can adapt to availability of features of the kernel
// driver. The message should not be altered.
func
(
ms
*
Server
)
KernelSettings
()
*
InitIn
{
ms
.
reqMu
.
Lock
()
s
:=
ms
.
kernelSettings
ms
.
reqMu
.
Unlock
()
return
&
s
}
const
_MAX_NAME_LEN
=
20
// This type may be provided for recording latencies of each FUSE
// operation.
type
LatencyMap
interface
{
Add
(
name
string
,
dt
time
.
Duration
)
}
// RecordLatencies switches on collection of timing for each request
// coming from the kernel.P assing a nil argument switches off the
func
(
ms
*
Server
)
RecordLatencies
(
l
LatencyMap
)
{
ms
.
latencies
=
l
}
// Unmount calls fusermount -u on the mount. This has the effect of
// shutting down the filesystem. After the Server is unmounted, it
// should be discarded.
func
(
ms
*
Server
)
Unmount
()
(
err
error
)
{
if
ms
.
mountPoint
==
""
{
return
nil
}
delay
:=
time
.
Duration
(
0
)
for
try
:=
0
;
try
<
5
;
try
++
{
err
=
unmount
(
ms
.
mountPoint
,
ms
.
opts
)
if
err
==
nil
{
break
}
// Sleep for a bit. This is not pretty, but there is
// no way we can be certain that the kernel thinks all
// open files have already been closed.
delay
=
2
*
delay
+
5
*
time
.
Millisecond
time
.
Sleep
(
delay
)
}
if
err
!=
nil
{
return
}
// Wait for event loops to exit.
ms
.
loops
.
Wait
()
ms
.
mountPoint
=
""
return
err
}
// NewServer creates a server and attaches it to the given directory.
func
NewServer
(
fs
RawFileSystem
,
mountPoint
string
,
opts
*
MountOptions
)
(
*
Server
,
error
)
{
if
opts
==
nil
{
opts
=
&
MountOptions
{
MaxBackground
:
_DEFAULT_BACKGROUND_TASKS
,
}
}
o
:=
*
opts
if
o
.
MaxWrite
<
0
{
o
.
MaxWrite
=
0
}
if
o
.
MaxWrite
==
0
{
o
.
MaxWrite
=
1
<<
16
}
if
o
.
MaxWrite
>
MAX_KERNEL_WRITE
{
o
.
MaxWrite
=
MAX_KERNEL_WRITE
}
if
o
.
Name
==
""
{
name
:=
fs
.
String
()
l
:=
len
(
name
)
if
l
>
_MAX_NAME_LEN
{
l
=
_MAX_NAME_LEN
}
o
.
Name
=
strings
.
Replace
(
name
[
:
l
],
","
,
";"
,
-
1
)
}
for
_
,
s
:=
range
o
.
optionsStrings
()
{
if
strings
.
Contains
(
s
,
","
)
{
return
nil
,
fmt
.
Errorf
(
"found ',' in option string %q"
,
s
)
}
}
ms
:=
&
Server
{
fileSystem
:
fs
,
opts
:
&
o
,
retrieveTab
:
make
(
map
[
uint64
]
*
retrieveCacheRequest
),
// OSX has races when multiple routines read from the
// FUSE device: on unmount, sometime some reads do not
// error-out, meaning that unmount will hang.
singleReader
:
runtime
.
GOOS
==
"darwin"
,
ready
:
make
(
chan
error
,
1
),
}
ms
.
reqPool
.
New
=
func
()
interface
{}
{
return
&
request
{
cancel
:
make
(
chan
struct
{}),
}
}
ms
.
readPool
.
New
=
func
()
interface
{}
{
buf
:=
make
([]
byte
,
o
.
MaxWrite
+
int
(
maxInputSize
)
+
logicalBlockSize
)
buf
=
alignSlice
(
buf
,
unsafe
.
Sizeof
(
WriteIn
{}),
logicalBlockSize
,
uintptr
(
o
.
MaxWrite
)
+
maxInputSize
)
return
buf
}
mountPoint
=
filepath
.
Clean
(
mountPoint
)
if
!
filepath
.
IsAbs
(
mountPoint
)
{
cwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
return
nil
,
err
}
mountPoint
=
filepath
.
Clean
(
filepath
.
Join
(
cwd
,
mountPoint
))
}
fd
,
err
:=
mount
(
mountPoint
,
&
o
,
ms
.
ready
)
if
err
!=
nil
{
return
nil
,
err
}
ms
.
mountPoint
=
mountPoint
ms
.
mountFd
=
fd
if
code
:=
ms
.
handleInit
();
!
code
.
Ok
()
{
syscall
.
Close
(
fd
)
// TODO - unmount as well?
return
nil
,
fmt
.
Errorf
(
"init: %s"
,
code
)
}
// This prepares for Serve being called somewhere, either
// synchronously or asynchronously.
ms
.
loops
.
Add
(
1
)
return
ms
,
nil
}
func
(
o
*
MountOptions
)
optionsStrings
()
[]
string
{
var
r
[]
string
r
=
append
(
r
,
o
.
Options
...
)
if
o
.
AllowOther
{
r
=
append
(
r
,
"allow_other"
)
}
if
o
.
FsName
!=
""
{
r
=
append
(
r
,
"fsname="
+
o
.
FsName
)
}
if
o
.
Name
!=
""
{
r
=
append
(
r
,
"subtype="
+
o
.
Name
)
}
return
r
}
// DebugData returns internal status information for debugging
// purposes.
func
(
ms
*
Server
)
DebugData
()
string
{
var
r
int
ms
.
reqMu
.
Lock
()
r
=
ms
.
reqReaders
ms
.
reqMu
.
Unlock
()
return
fmt
.
Sprintf
(
"readers: %d"
,
r
)
}
// What is a good number? Maybe the number of CPUs?
const
_MAX_READERS
=
2
// handleEINTR retries the given function until it doesn't return syscall.EINTR.
// This is similar to the HANDLE_EINTR() macro from Chromium ( see
// https://code.google.com/p/chromium/codesearch#chromium/src/base/posix/eintr_wrapper.h
// ) and the TEMP_FAILURE_RETRY() from glibc (see
// https://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html
// ).
//
// Don't use handleEINTR() with syscall.Close(); see
// https://code.google.com/p/chromium/issues/detail?id=269623 .
func
handleEINTR
(
fn
func
()
error
)
(
err
error
)
{
for
{
err
=
fn
()
if
err
!=
syscall
.
EINTR
{
break
}
}
return
}
// Returns a new request, or error. In case exitIdle is given, returns
// nil, OK if we have too many readers already.
func
(
ms
*
Server
)
readRequest
(
exitIdle
bool
)
(
req
*
request
,
code
Status
)
{
req
=
ms
.
reqPool
.
Get
()
.
(
*
request
)
dest
:=
ms
.
readPool
.
Get
()
.
([]
byte
)
ms
.
reqMu
.
Lock
()
if
ms
.
reqReaders
>
_MAX_READERS
{
ms
.
reqMu
.
Unlock
()
return
nil
,
OK
}
ms
.
reqReaders
++
ms
.
reqMu
.
Unlock
()
var
n
int
err
:=
handleEINTR
(
func
()
error
{
var
err
error
n
,
err
=
syscall
.
Read
(
ms
.
mountFd
,
dest
)
return
err
})
if
err
!=
nil
{
code
=
ToStatus
(
err
)
ms
.
reqPool
.
Put
(
req
)
ms
.
reqMu
.
Lock
()
ms
.
reqReaders
--
ms
.
reqMu
.
Unlock
()
return
nil
,
code
}
if
ms
.
latencies
!=
nil
{
req
.
startTime
=
time
.
Now
()
}
gobbled
:=
req
.
setInput
(
dest
[
:
n
])
ms
.
reqMu
.
Lock
()
defer
ms
.
reqMu
.
Unlock
()
// Must parse request.Unique under lock
if
status
:=
req
.
parseHeader
();
!
status
.
Ok
()
{
return
nil
,
status
}
req
.
inflightIndex
=
len
(
ms
.
reqInflight
)
ms
.
reqInflight
=
append
(
ms
.
reqInflight
,
req
)
if
!
gobbled
{
ms
.
readPool
.
Put
(
dest
)
dest
=
nil
}
ms
.
reqReaders
--
if
!
ms
.
singleReader
&&
ms
.
reqReaders
<=
0
{
ms
.
loops
.
Add
(
1
)
go
ms
.
loop
(
true
)
}
return
req
,
OK
}
// returnRequest returns a request to the pool of unused requests.
func
(
ms
*
Server
)
returnRequest
(
req
*
request
)
{
ms
.
reqMu
.
Lock
()
this
:=
req
.
inflightIndex
last
:=
len
(
ms
.
reqInflight
)
-
1
if
last
!=
this
{
ms
.
reqInflight
[
this
]
=
ms
.
reqInflight
[
last
]
ms
.
reqInflight
[
this
]
.
inflightIndex
=
this
}
ms
.
reqInflight
=
ms
.
reqInflight
[
:
last
]
interrupted
:=
req
.
interrupted
ms
.
reqMu
.
Unlock
()
ms
.
recordStats
(
req
)
if
interrupted
{
// Don't reposses data, because someone might still
// be looking at it
return
}
if
req
.
bufferPoolOutputBuf
!=
nil
{
ms
.
buffers
.
FreeBuffer
(
req
.
bufferPoolOutputBuf
)
req
.
bufferPoolOutputBuf
=
nil
}
req
.
clear
()
if
p
:=
req
.
bufferPoolInputBuf
;
p
!=
nil
{
req
.
bufferPoolInputBuf
=
nil
ms
.
readPool
.
Put
(
p
)
}
ms
.
reqPool
.
Put
(
req
)
}
func
(
ms
*
Server
)
recordStats
(
req
*
request
)
{
if
ms
.
latencies
!=
nil
{
dt
:=
time
.
Now
()
.
Sub
(
req
.
startTime
)
opname
:=
operationName
(
req
.
inHeader
.
Opcode
)
ms
.
latencies
.
Add
(
opname
,
dt
)
}
}
// Serve initiates the FUSE loop. Normally, callers should run Serve()
// and wait for it to exit, but tests will want to run this in a
// goroutine.
//
// Each filesystem operation executes in a separate goroutine.
func
(
ms
*
Server
)
Serve
()
{
ms
.
loop
(
false
)
ms
.
loops
.
Wait
()
ms
.
writeMu
.
Lock
()
syscall
.
Close
(
ms
.
mountFd
)
ms
.
writeMu
.
Unlock
()
// shutdown in-flight cache retrieves.
//
// It is possible that umount comes in the middle - after retrieve
// request was sent to kernel, but corresponding kernel reply has not
// yet been read. We unblock all such readers and wake them up with ENODEV.
ms
.
retrieveMu
.
Lock
()
rtab
:=
ms
.
retrieveTab
// retrieve attempts might be erroneously tried even after close
// we have to keep retrieveTab !nil not to panic.
ms
.
retrieveTab
=
make
(
map
[
uint64
]
*
retrieveCacheRequest
)
ms
.
retrieveMu
.
Unlock
()
for
_
,
reading
:=
range
rtab
{
reading
.
n
=
0
reading
.
st
=
ENODEV
close
(
reading
.
ready
)
}
}
// Wait waits for the serve loop to exit. This should only be called
// after Serve has been called, or it will hang indefinitely.
func
(
ms
*
Server
)
Wait
()
{
ms
.
loops
.
Wait
()
}
func
(
ms
*
Server
)
handleInit
()
Status
{
// The first request should be INIT; read it synchronously,
// and don't spawn new readers.
orig
:=
ms
.
singleReader
ms
.
singleReader
=
true
req
,
errNo
:=
ms
.
readRequest
(
false
)
ms
.
singleReader
=
orig
if
errNo
!=
OK
||
req
==
nil
{
return
errNo
}
if
code
:=
ms
.
handleRequest
(
req
);
!
code
.
Ok
()
{
return
code
}
// INIT is handled. Init the file system, but don't accept
// incoming requests, so the file system can setup itself.
ms
.
fileSystem
.
Init
(
ms
)
return
OK
}
func
(
ms
*
Server
)
loop
(
exitIdle
bool
)
{
defer
ms
.
loops
.
Done
()
exit
:
for
{
req
,
errNo
:=
ms
.
readRequest
(
exitIdle
)
switch
errNo
{
case
OK
:
if
req
==
nil
{
break
exit
}
case
ENOENT
:
continue
case
ENODEV
:
// unmount
if
ms
.
opts
.
Debug
{
log
.
Printf
(
"received ENODEV (unmount request), thread exiting"
)
}
break
exit
default
:
// some other error?
log
.
Printf
(
"Failed to read from fuse conn: %v"
,
errNo
)
break
exit
}
if
ms
.
singleReader
{
go
ms
.
handleRequest
(
req
)
}
else
{
ms
.
handleRequest
(
req
)
}
}
}
func
(
ms
*
Server
)
handleRequest
(
req
*
request
)
Status
{
if
ms
.
opts
.
SingleThreaded
{
ms
.
requestProcessingMu
.
Lock
()
defer
ms
.
requestProcessingMu
.
Unlock
()
}
req
.
parse
()
if
req
.
handler
==
nil
{
req
.
status
=
ENOSYS
}
if
req
.
status
.
Ok
()
&&
ms
.
opts
.
Debug
{
log
.
Println
(
req
.
InputDebug
())
}
if
req
.
inHeader
.
NodeId
==
pollHackInode
||
req
.
inHeader
.
NodeId
==
FUSE_ROOT_ID
&&
len
(
req
.
filenames
)
>
0
&&
req
.
filenames
[
0
]
==
pollHackName
{
doPollHackLookup
(
ms
,
req
)
}
else
if
req
.
status
.
Ok
()
&&
req
.
handler
.
Func
==
nil
{
log
.
Printf
(
"Unimplemented opcode %v"
,
operationName
(
req
.
inHeader
.
Opcode
))
req
.
status
=
ENOSYS
}
else
if
req
.
status
.
Ok
()
{
req
.
handler
.
Func
(
ms
,
req
)
}
errNo
:=
ms
.
write
(
req
)
if
errNo
!=
0
{
log
.
Printf
(
"writer: Write/Writev failed, err: %v. opcode: %v"
,
errNo
,
operationName
(
req
.
inHeader
.
Opcode
))
}
ms
.
returnRequest
(
req
)
return
Status
(
errNo
)
}
// alignSlice ensures that the byte at alignedByte is aligned with the
// given logical block size. The input slice should be at least (size
// + blockSize)
func
alignSlice
(
buf
[]
byte
,
alignedByte
,
blockSize
,
size
uintptr
)
[]
byte
{
misaligned
:=
uintptr
(
unsafe
.
Pointer
(
&
buf
[
alignedByte
]))
&
(
blockSize
-
1
)
buf
=
buf
[
blockSize
-
misaligned
:
]
return
buf
[
:
size
]
}
func
(
ms
*
Server
)
allocOut
(
req
*
request
,
size
uint32
)
[]
byte
{
if
cap
(
req
.
bufferPoolOutputBuf
)
>=
int
(
size
)
{
req
.
bufferPoolOutputBuf
=
req
.
bufferPoolOutputBuf
[
:
size
]
return
req
.
bufferPoolOutputBuf
}
if
req
.
bufferPoolOutputBuf
!=
nil
{
ms
.
buffers
.
FreeBuffer
(
req
.
bufferPoolOutputBuf
)
req
.
bufferPoolOutputBuf
=
nil
}
// As this allocated a multiple of the page size, very likely
// this is aligned to logicalBlockSize too, which is smaller.
req
.
bufferPoolOutputBuf
=
ms
.
buffers
.
AllocBuffer
(
size
)
return
req
.
bufferPoolOutputBuf
}
func
(
ms
*
Server
)
write
(
req
*
request
)
Status
{
// Forget/NotifyReply do not wait for reply from filesystem server.
switch
req
.
inHeader
.
Opcode
{
case
_OP_FORGET
,
_OP_BATCH_FORGET
,
_OP_NOTIFY_REPLY
:
return
OK
case
_OP_INTERRUPT
:
if
req
.
status
.
Ok
()
{
return
OK
}
}
header
:=
req
.
serializeHeader
(
req
.
flatDataSize
())
if
ms
.
opts
.
Debug
{
log
.
Println
(
req
.
OutputDebug
())
}
if
header
==
nil
{
return
OK
}
s
:=
ms
.
systemWrite
(
req
,
header
)
return
s
}
// InodeNotify invalidates the information associated with the inode
// (ie. data cache, attributes, etc.)
func
(
ms
*
Server
)
InodeNotify
(
node
uint64
,
off
int64
,
length
int64
)
Status
{
if
!
ms
.
kernelSettings
.
SupportsNotify
(
NOTIFY_INVAL_INODE
)
{
return
ENOSYS
}
req
:=
request
{
inHeader
:
&
InHeader
{
Opcode
:
_OP_NOTIFY_INVAL_INODE
,
},
handler
:
operationHandlers
[
_OP_NOTIFY_INVAL_INODE
],
status
:
NOTIFY_INVAL_INODE
,
}
entry
:=
(
*
NotifyInvalInodeOut
)(
req
.
outData
())
entry
.
Ino
=
node
entry
.
Off
=
off
entry
.
Length
=
length
// Protect against concurrent close.
ms
.
writeMu
.
Lock
()
result
:=
ms
.
write
(
&
req
)
ms
.
writeMu
.
Unlock
()
if
ms
.
opts
.
Debug
{
log
.
Println
(
"Response: INODE_NOTIFY"
,
result
)
}
return
result
}
// InodeNotifyStoreCache tells kernel to store data into inode's cache.
//
// This call is similar to InodeNotify, but instead of only invalidating a data
// region, it gives updated data directly to the kernel.
func
(
ms
*
Server
)
InodeNotifyStoreCache
(
node
uint64
,
offset
int64
,
data
[]
byte
)
Status
{
if
!
ms
.
kernelSettings
.
SupportsNotify
(
NOTIFY_STORE_CACHE
)
{
return
ENOSYS
}
for
len
(
data
)
>
0
{
size
:=
len
(
data
)
if
size
>
math
.
MaxInt32
{
// NotifyStoreOut has only uint32 for size.
// we check for max(int32), not max(uint32), because on 32-bit
// platforms int has only 31-bit for positive range.
size
=
math
.
MaxInt32
}
st
:=
ms
.
inodeNotifyStoreCache32
(
node
,
offset
,
data
[
:
size
])
if
st
!=
OK
{
return
st
}
data
=
data
[
size
:
]
offset
+=
int64
(
size
)
}
return
OK
}
// inodeNotifyStoreCache32 is internal worker for InodeNotifyStoreCache which
// handles data chunks not larger than 2GB.
func
(
ms
*
Server
)
inodeNotifyStoreCache32
(
node
uint64
,
offset
int64
,
data
[]
byte
)
Status
{
req
:=
request
{
inHeader
:
&
InHeader
{
Opcode
:
_OP_NOTIFY_STORE_CACHE
,
},
handler
:
operationHandlers
[
_OP_NOTIFY_STORE_CACHE
],
status
:
NOTIFY_STORE_CACHE
,
}
store
:=
(
*
NotifyStoreOut
)(
req
.
outData
())
store
.
Nodeid
=
node
store
.
Offset
=
uint64
(
offset
)
// NOTE not int64, as it is e.g. in NotifyInvalInodeOut
store
.
Size
=
uint32
(
len
(
data
))
req
.
flatData
=
data
// Protect against concurrent close.
ms
.
writeMu
.
Lock
()
result
:=
ms
.
write
(
&
req
)
ms
.
writeMu
.
Unlock
()
if
ms
.
opts
.
Debug
{
log
.
Printf
(
"Response: INODE_NOTIFY_STORE_CACHE: %v"
,
result
)
}
return
result
}
// InodeRetrieveCache retrieves data from kernel's inode cache.
//
// InodeRetrieveCache asks kernel to return data from its cache for inode at
// [offset:offset+len(dest)) and waits for corresponding reply. If kernel cache
// has fewer consecutive data starting at offset, that fewer amount is returned.
// In particular if inode data at offset is not cached (0, OK) is returned.
//
// The kernel returns ENOENT if it does not currently have entry for this inode
// in its dentry cache.
func
(
ms
*
Server
)
InodeRetrieveCache
(
node
uint64
,
offset
int64
,
dest
[]
byte
)
(
n
int
,
st
Status
)
{
// the kernel won't send us in one go more then what we negotiated as MaxWrite.
// retrieve the data in chunks.
// TODO spawn some number of readahead retrievers in parallel.
ntotal
:=
0
for
{
chunkSize
:=
len
(
dest
)
if
chunkSize
>
ms
.
opts
.
MaxWrite
{
chunkSize
=
ms
.
opts
.
MaxWrite
}
n
,
st
=
ms
.
inodeRetrieveCache1
(
node
,
offset
,
dest
[
:
chunkSize
])
if
st
!=
OK
||
n
==
0
{
break
}
ntotal
+=
n
offset
+=
int64
(
n
)
dest
=
dest
[
n
:
]
}
// if we could retrieve at least something - it is ok.
// if ntotal=0 - st will be st returned from first inodeRetrieveCache1.
if
ntotal
>
0
{
st
=
OK
}
return
ntotal
,
st
}
// inodeRetrieveCache1 is internal worker for InodeRetrieveCache which
// actually talks to kernel and retrieves chunks not larger than ms.opts.MaxWrite.
func
(
ms
*
Server
)
inodeRetrieveCache1
(
node
uint64
,
offset
int64
,
dest
[]
byte
)
(
n
int
,
st
Status
)
{
if
!
ms
.
kernelSettings
.
SupportsNotify
(
NOTIFY_RETRIEVE_CACHE
)
{
return
0
,
ENOSYS
}
req
:=
request
{
inHeader
:
&
InHeader
{
Opcode
:
_OP_NOTIFY_RETRIEVE_CACHE
,
},
handler
:
operationHandlers
[
_OP_NOTIFY_RETRIEVE_CACHE
],
status
:
NOTIFY_RETRIEVE_CACHE
,
}
// retrieve up to 2GB not to overflow uint32 size in NotifyRetrieveOut.
// see InodeNotifyStoreCache in similar place for why it is only 2GB, not 4GB.
//
// ( InodeRetrieveCache calls us with chunks not larger than
// ms.opts.MaxWrite, but MaxWrite is int, so let's be extra cautious )
size
:=
len
(
dest
)
if
size
>
math
.
MaxInt32
{
size
=
math
.
MaxInt32
}
dest
=
dest
[
:
size
]
q
:=
(
*
NotifyRetrieveOut
)(
req
.
outData
())
q
.
Nodeid
=
node
q
.
Offset
=
uint64
(
offset
)
// not int64, as it is e.g. in NotifyInvalInodeOut
q
.
Size
=
uint32
(
len
(
dest
))
reading
:=
&
retrieveCacheRequest
{
nodeid
:
q
.
Nodeid
,
offset
:
q
.
Offset
,
dest
:
dest
,
ready
:
make
(
chan
struct
{}),
}
ms
.
retrieveMu
.
Lock
()
q
.
NotifyUnique
=
ms
.
retrieveNext
ms
.
retrieveNext
++
ms
.
retrieveTab
[
q
.
NotifyUnique
]
=
reading
ms
.
retrieveMu
.
Unlock
()
// Protect against concurrent close.
ms
.
writeMu
.
Lock
()
result
:=
ms
.
write
(
&
req
)
ms
.
writeMu
.
Unlock
()
if
ms
.
opts
.
Debug
{
log
.
Printf
(
"Response: NOTIFY_RETRIEVE_CACHE: %v"
,
result
)
}
if
result
!=
OK
{
ms
.
retrieveMu
.
Lock
()
r
:=
ms
.
retrieveTab
[
q
.
NotifyUnique
]
if
r
==
reading
{
delete
(
ms
.
retrieveTab
,
q
.
NotifyUnique
)
}
else
if
r
==
nil
{
// ok - might be dequeued by umount
}
else
{
// although very unlikely, it is possible that kernel sends
// unexpected NotifyReply with our notifyUnique, then
// retrieveNext wraps, makes full cycle, and another
// retrieve request is made with the same notifyUnique.
log
.
Printf
(
"W: INODE_RETRIEVE_CACHE: request with notifyUnique=%d mutated"
,
q
.
NotifyUnique
)
}
ms
.
retrieveMu
.
Unlock
()
return
0
,
result
}
// NotifyRetrieveOut sent to the kernel successfully. Now the kernel
// have to return data in a separate write-style NotifyReply request.
// Wait for the result.
<-
reading
.
ready
return
reading
.
n
,
reading
.
st
}
// retrieveCacheRequest represents in-flight cache retrieve request.
type
retrieveCacheRequest
struct
{
nodeid
uint64
offset
uint64
dest
[]
byte
// reply status
n
int
st
Status
ready
chan
struct
{}
}
// DeleteNotify notifies the kernel that an entry is removed from a
// directory. In many cases, this is equivalent to EntryNotify,
// except when the directory is in use, eg. as working directory of
// some process. You should not hold any FUSE filesystem locks, as that
// can lead to deadlock.
func
(
ms
*
Server
)
DeleteNotify
(
parent
uint64
,
child
uint64
,
name
string
)
Status
{
if
ms
.
kernelSettings
.
Minor
<
18
{
return
ms
.
EntryNotify
(
parent
,
name
)
}
req
:=
request
{
inHeader
:
&
InHeader
{
Opcode
:
_OP_NOTIFY_DELETE
,
},
handler
:
operationHandlers
[
_OP_NOTIFY_DELETE
],
status
:
NOTIFY_DELETE
,
}
entry
:=
(
*
NotifyInvalDeleteOut
)(
req
.
outData
())
entry
.
Parent
=
parent
entry
.
Child
=
child
entry
.
NameLen
=
uint32
(
len
(
name
))
// Many versions of FUSE generate stacktraces if the
// terminating null byte is missing.
nameBytes
:=
make
([]
byte
,
len
(
name
)
+
1
)
copy
(
nameBytes
,
name
)
nameBytes
[
len
(
nameBytes
)
-
1
]
=
'\000'
req
.
flatData
=
nameBytes
// Protect against concurrent close.
ms
.
writeMu
.
Lock
()
result
:=
ms
.
write
(
&
req
)
ms
.
writeMu
.
Unlock
()
if
ms
.
opts
.
Debug
{
log
.
Printf
(
"Response: DELETE_NOTIFY: %v"
,
result
)
}
return
result
}
// EntryNotify should be used if the existence status of an entry
// within a directory changes. You should not hold any FUSE filesystem
// locks, as that can lead to deadlock.
func
(
ms
*
Server
)
EntryNotify
(
parent
uint64
,
name
string
)
Status
{
if
!
ms
.
kernelSettings
.
SupportsNotify
(
NOTIFY_INVAL_ENTRY
)
{
return
ENOSYS
}
req
:=
request
{
inHeader
:
&
InHeader
{
Opcode
:
_OP_NOTIFY_INVAL_ENTRY
,
},
handler
:
operationHandlers
[
_OP_NOTIFY_INVAL_ENTRY
],
status
:
NOTIFY_INVAL_ENTRY
,
}
entry
:=
(
*
NotifyInvalEntryOut
)(
req
.
outData
())
entry
.
Parent
=
parent
entry
.
NameLen
=
uint32
(
len
(
name
))
// Many versions of FUSE generate stacktraces if the
// terminating null byte is missing.
nameBytes
:=
make
([]
byte
,
len
(
name
)
+
1
)
copy
(
nameBytes
,
name
)
nameBytes
[
len
(
nameBytes
)
-
1
]
=
'\000'
req
.
flatData
=
nameBytes
// Protect against concurrent close.
ms
.
writeMu
.
Lock
()
result
:=
ms
.
write
(
&
req
)
ms
.
writeMu
.
Unlock
()
if
ms
.
opts
.
Debug
{
log
.
Printf
(
"Response: ENTRY_NOTIFY: %v"
,
result
)
}
return
result
}
// SupportsVersion returns true if the kernel supports the given
// protocol version or newer.
func
(
in
*
InitIn
)
SupportsVersion
(
maj
,
min
uint32
)
bool
{
return
in
.
Major
>
maj
||
(
in
.
Major
==
maj
&&
in
.
Minor
>=
min
)
}
// SupportsNotify returns whether a certain notification type is
// supported. Pass any of the NOTIFY_* types as argument.
func
(
in
*
InitIn
)
SupportsNotify
(
notifyType
int
)
bool
{
switch
notifyType
{
case
NOTIFY_INVAL_ENTRY
:
return
in
.
SupportsVersion
(
7
,
12
)
case
NOTIFY_INVAL_INODE
:
return
in
.
SupportsVersion
(
7
,
12
)
case
NOTIFY_STORE_CACHE
,
NOTIFY_RETRIEVE_CACHE
:
return
in
.
SupportsVersion
(
7
,
15
)
case
NOTIFY_DELETE
:
return
in
.
SupportsVersion
(
7
,
18
)
}
return
false
}
// WaitMount waits for the first request to be served. Use this to
// avoid racing between accessing the (empty or not yet mounted)
// mountpoint, and the OS trying to setup the user-space mount.
func
(
ms
*
Server
)
WaitMount
()
error
{
err
:=
<-
ms
.
ready
if
err
!=
nil
{
return
err
}
return
pollHack
(
ms
.
mountPoint
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/server_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/splice_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/splice_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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/v2/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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/syscall_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/syscall_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/typeprint.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
a
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"time"
)
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
)
// EINTR Call was interrupted
EINTR
=
Status
(
syscall
.
EINTR
)
// 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
)
// ENOTSUP Not supported
ENOTSUP
=
Status
(
syscall
.
ENOTSUP
)
// EISDIR Is a directory
EISDIR
=
Status
(
syscall
.
EISDIR
)
// 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
// The mode for the new directory. The calling process' umask
// is already factored into the mode.
Mode
uint32
Umask
uint32
}
type
Rename1In
struct
{
InHeader
Newdir
uint64
}
type
RenameIn
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
}
// GetFh returns the file handle if available, or 0 if undefined.
func
(
s
*
SetAttrInCommon
)
GetFh
()
(
uint64
,
bool
)
{
if
s
.
Valid
&
FATTR_FH
!=
0
{
return
s
.
Fh
,
true
}
return
0
,
false
}
func
(
s
*
SetAttrInCommon
)
GetMode
()
(
uint32
,
bool
)
{
if
s
.
Valid
&
FATTR_MODE
!=
0
{
return
s
.
Mode
&
07777
,
true
}
return
0
,
false
}
func
(
s
*
SetAttrInCommon
)
GetUID
()
(
uint32
,
bool
)
{
if
s
.
Valid
&
FATTR_UID
!=
0
{
return
s
.
Uid
,
true
}
return
^
uint32
(
0
),
false
}
func
(
s
*
SetAttrInCommon
)
GetGID
()
(
uint32
,
bool
)
{
if
s
.
Valid
&
FATTR_GID
!=
0
{
return
s
.
Gid
,
true
}
return
^
uint32
(
0
),
false
}
func
(
s
*
SetAttrInCommon
)
GetSize
()
(
uint64
,
bool
)
{
if
s
.
Valid
&
FATTR_SIZE
!=
0
{
return
s
.
Size
,
true
}
return
0
,
false
}
func
(
s
*
SetAttrInCommon
)
GetMTime
()
(
time
.
Time
,
bool
)
{
var
t
time
.
Time
if
s
.
Valid
&
FATTR_MTIME
!=
0
{
if
s
.
Valid
&
FATTR_MTIME_NOW
!=
0
{
t
=
time
.
Now
()
}
else
{
t
=
time
.
Unix
(
int64
(
s
.
Mtime
),
int64
(
s
.
Mtimensec
))
}
return
t
,
true
}
return
t
,
false
}
func
(
s
*
SetAttrInCommon
)
GetATime
()
(
time
.
Time
,
bool
)
{
var
t
time
.
Time
if
s
.
Valid
&
FATTR_ATIME
!=
0
{
if
s
.
Valid
&
FATTR_ATIME_NOW
!=
0
{
t
=
time
.
Now
()
}
else
{
t
=
time
.
Unix
(
int64
(
s
.
Atime
),
int64
(
s
.
Atimensec
))
}
return
t
,
true
}
return
t
,
false
}
func
(
s
*
SetAttrInCommon
)
GetCTime
()
(
time
.
Time
,
bool
)
{
var
t
time
.
Time
if
s
.
Valid
&
FATTR_CTIME
!=
0
{
t
=
time
.
Unix
(
int64
(
s
.
Ctime
),
int64
(
s
.
Ctimensec
))
return
t
,
true
}
return
t
,
false
}
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
)
FOPEN_CACHE_DIR
=
(
1
<<
3
)
FOPEN_STREAM
=
(
1
<<
4
)
)
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
)
CAP_PARALLEL_DIROPS
=
(
1
<<
18
)
CAP_HANDLE_KILLPRIV
=
(
1
<<
19
)
CAP_POSIX_ACL
=
(
1
<<
20
)
CAP_ABORT_ERROR
=
(
1
<<
21
)
CAP_MAX_PAGES
=
(
1
<<
22
)
CAP_CACHE_SYMLINKS
=
(
1
<<
23
)
CAP_NO_OPENDIR_SUPPORT
=
(
1
<<
24
)
CAP_EXPLICIT_INVAL_DATA
=
(
1
<<
25
)
)
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
MaxPages
uint16
Padding
uint16
Unused
[
8
]
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
}
type
NotifyStoreOut
struct
{
Nodeid
uint64
Offset
uint64
Size
uint32
Padding
uint32
}
type
NotifyRetrieveOut
struct
{
NotifyUnique
uint64
Nodeid
uint64
Offset
uint64
Size
uint32
Padding
uint32
}
type
NotifyRetrieveIn
struct
{
InHeader
Dummy1
uint64
Offset
uint64
Size
uint32
Dummy2
uint32
Dummy3
uint64
Dummy4
uint64
}
const
(
// NOTIFY_POLL = -1 // notify kernel that a poll waiting for IO on a file handle should wake up
NOTIFY_INVAL_INODE
=
-
2
// notify kernel that an inode should be invalidated
NOTIFY_INVAL_ENTRY
=
-
3
// notify kernel that a directory entry should be invalidated
NOTIFY_STORE_CACHE
=
-
4
// store data into kernel cache of an inode
NOTIFY_RETRIEVE_CACHE
=
-
5
// retrieve data from kernel cache of an inode
NOTIFY_DELETE
=
-
6
// notify kernel that a directory entry has been deleted
// NOTIFY_CODE_MAX = -6
)
type
FlushIn
struct
{
InHeader
Fh
uint64
Unused
uint32
Padding
uint32
LockOwner
uint64
}
type
LseekIn
struct
{
InHeader
Fh
uint64
Offset
uint64
Whence
uint32
Padding
uint32
}
type
LseekOut
struct
{
Offset
uint64
}
type
CopyFileRangeIn
struct
{
InHeader
FhIn
uint64
OffIn
uint64
NodeIdOut
uint64
FhOut
uint64
OffOut
uint64
Len
uint64
Flags
uint64
}
// EntryOut holds the result of a (directory,name) lookup. It has two
// TTLs, one for the (directory, name) lookup itself, and one for the
// attributes (eg. size, mode). The entry TTL also applies if the
// lookup result is ENOENT ("negative entry lookup")
type
EntryOut
struct
{
NodeId
uint64
Generation
uint64
EntryValid
uint64
AttrValid
uint64
EntryValidNsec
uint32
AttrValidNsec
uint32
Attr
}
// EntryTimeout returns entry timeout currently
func
(
o
*
EntryOut
)
EntryTimeout
()
time
.
Duration
{
return
time
.
Duration
(
uint64
(
o
.
EntryValidNsec
)
+
o
.
EntryValid
*
1e9
)
}
func
(
o
*
EntryOut
)
AttrTimeout
()
time
.
Duration
{
return
time
.
Duration
(
uint64
(
o
.
AttrValidNsec
)
+
o
.
AttrValid
*
1e9
)
}
func
(
o
*
EntryOut
)
SetEntryTimeout
(
dt
time
.
Duration
)
{
ns
:=
int64
(
dt
)
o
.
EntryValidNsec
=
uint32
(
ns
%
1e9
)
o
.
EntryValid
=
uint64
(
ns
/
1e9
)
}
func
(
o
*
EntryOut
)
SetAttrTimeout
(
dt
time
.
Duration
)
{
ns
:=
int64
(
dt
)
o
.
AttrValidNsec
=
uint32
(
ns
%
1e9
)
o
.
AttrValid
=
uint64
(
ns
/
1e9
)
}
type
AttrOut
struct
{
AttrValid
uint64
AttrValidNsec
uint32
Dummy
uint32
Attr
}
func
(
o
*
AttrOut
)
Timeout
()
time
.
Duration
{
return
time
.
Duration
(
uint64
(
o
.
AttrValidNsec
)
+
o
.
AttrValid
*
1e9
)
}
func
(
o
*
AttrOut
)
SetTimeout
(
dt
time
.
Duration
)
{
ns
:=
int64
(
dt
)
o
.
AttrValidNsec
=
uint32
(
ns
%
1e9
)
o
.
AttrValid
=
uint64
(
ns
/
1e9
)
}
type
CreateOut
struct
{
EntryOut
OpenOut
}
// Caller has data on the process making the FS call.
//
// The UID and GID are effective UID/GID, except for the ACCESS
// opcode, where UID and GID are the real UIDs
type
Caller
struct
{
Owner
Pid
uint32
}
type
InHeader
struct
{
Length
uint32
Opcode
uint32
Unique
uint64
NodeId
uint64
Caller
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
}
func
(
lk
*
FileLock
)
ToFlockT
(
flockT
*
syscall
.
Flock_t
)
{
flockT
.
Start
=
int64
(
lk
.
Start
)
if
lk
.
End
==
(
1
<<
63
)
-
1
{
flockT
.
Len
=
0
}
else
{
flockT
.
Len
=
int64
(
lk
.
End
-
lk
.
Start
+
1
)
}
flockT
.
Whence
=
int16
(
io
.
SeekStart
)
flockT
.
Type
=
int16
(
lk
.
Typ
)
}
func
(
lk
*
FileLock
)
FromFlockT
(
flockT
*
syscall
.
Flock_t
)
{
lk
.
Typ
=
uint32
(
flockT
.
Type
)
if
flockT
.
Type
!=
syscall
.
F_UNLCK
{
lk
.
Start
=
uint64
(
flockT
.
Start
)
if
flockT
.
Len
==
0
{
lk
.
End
=
(
1
<<
63
)
-
1
}
else
{
lk
.
End
=
uint64
(
flockT
.
Start
+
flockT
.
Len
-
1
)
}
}
lk
.
Pid
=
uint32
(
flockT
.
Pid
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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.
// EREMOTEIO is not supported on Darwin.
EREMOTEIO
=
Status
(
syscall
.
EIO
)
)
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.
// The block counts are in units of statfs.Bsize.
// If s.Bsize != statfs.Bsize, we have to recalculate the block counts
// accordingly (s.Bsize is usually 256*statfs.Bsize).
if
s
.
Bsize
>
statfs
.
Bsize
{
adj
:=
uint64
(
s
.
Bsize
/
statfs
.
Bsize
)
s
.
Blocks
/=
adj
s
.
Bfree
/=
adj
s
.
Bavail
/=
adj
}
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/fuse/types_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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.
// EREMOTEIO Remote I/O error
EREMOTEIO
=
Status
(
syscall
.
EREMOTEIO
)
)
type
Attr
struct
{
Ino
uint64
Size
uint64
// Blocks is the number of 512-byte blocks that the file occupies on disk.
Blocks
uint64
Atime
uint64
Mtime
uint64
Ctime
uint64
Atimensec
uint32
Mtimensec
uint32
Ctimensec
uint32
Mode
uint32
Nlink
uint32
Owner
Rdev
uint32
// Blksize is the preferred size for file system operations.
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 for the new file; already takes Umask into account.
Mode
uint32
// Umask used for this create call.
Umask
uint32
Padding
uint32
}
type
MknodIn
struct
{
InHeader
// Mode to use, including the Umask value
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
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/internal/utimens/utimens_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// Copyright 2018 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
utimens
import
(
"syscall"
"time"
"github.com/hanwen/go-fuse/v2/fuse"
)
// timeToTimeval converts time.Time to syscall.Timeval
func
timeToTimeval
(
t
*
time
.
Time
)
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
var
tv
syscall
.
Timeval
tv
.
Usec
=
int32
(
t
.
Nanosecond
()
/
1000
)
tv
.
Sec
=
t
.
Unix
()
return
tv
}
// Fill converts a and m to a syscall.Timeval slice that can be passed
// to syscall.Utimes. Missing values (if any) are taken from attr
func
Fill
(
a
*
time
.
Time
,
m
*
time
.
Time
,
attr
*
fuse
.
Attr
)
[]
syscall
.
Timeval
{
if
a
==
nil
{
a2
:=
time
.
Unix
(
int64
(
attr
.
Atime
),
int64
(
attr
.
Atimensec
))
a
=
&
a2
}
if
m
==
nil
{
m2
:=
time
.
Unix
(
int64
(
attr
.
Mtime
),
int64
(
attr
.
Mtimensec
))
m
=
&
m2
}
tv
:=
make
([]
syscall
.
Timeval
,
2
)
tv
[
0
]
=
timeToTimeval
(
a
)
tv
[
1
]
=
timeToTimeval
(
m
)
return
tv
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/internal/utimens/utimens_linux.go
deleted
100644 → 0
View file @
e3e61d67
// Copyright 2018 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
utimens
// placeholder file so this package exists on all platforms.
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/copy.go
deleted
100644 → 0
View file @
e3e61d67
// 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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"syscall"
)
type
Pair
struct
{
r
,
w
int
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
(
uintptr
(
p
.
r
),
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
:=
syscall
.
Close
(
p
.
r
)
err2
:=
syscall
.
Close
(
p
.
w
)
if
err1
!=
nil
{
return
err1
}
return
err2
}
func
(
p
*
Pair
)
Read
(
d
[]
byte
)
(
n
int
,
err
error
)
{
return
syscall
.
Read
(
p
.
r
,
d
)
}
func
(
p
*
Pair
)
Write
(
d
[]
byte
)
(
n
int
,
err
error
)
{
return
syscall
.
Write
(
p
.
w
,
d
)
}
func
(
p
*
Pair
)
ReadFd
()
uintptr
{
return
uintptr
(
p
.
r
)
}
func
(
p
*
Pair
)
WriteFd
()
uintptr
{
return
uintptr
(
p
.
w
)
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair_darwin.go
deleted
100644 → 0
View file @
e3e61d67
// 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
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pair_linux.go
deleted
100644 → 0
View file @
e3e61d67
// 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"
"log"
"os"
"syscall"
)
func
(
p
*
Pair
)
LoadFromAt
(
fd
uintptr
,
sz
int
,
off
int64
)
(
int
,
error
)
{
n
,
err
:=
syscall
.
Splice
(
int
(
fd
),
&
off
,
p
.
w
,
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
,
p
.
w
,
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
(
p
.
r
,
nil
,
int
(
fd
),
nil
,
int
(
n
),
0
)
if
err
!=
nil
{
err
=
os
.
NewSyscallError
(
"Splice write"
,
err
)
}
return
int
(
m
),
err
}
const
_SPLICE_F_NONBLOCK
=
0x2
func
(
p
*
Pair
)
discard
()
{
_
,
err
:=
syscall
.
Splice
(
p
.
r
,
nil
,
int
(
devNullFD
),
nil
,
int
(
p
.
size
),
_SPLICE_F_NONBLOCK
)
if
err
==
syscall
.
EAGAIN
{
// all good.
}
else
if
err
!=
nil
{
errR
:=
syscall
.
Close
(
p
.
r
)
errW
:=
syscall
.
Close
(
p
.
w
)
// This can happen if something closed our fd
// inadvertently (eg. double close)
log
.
Panicf
(
"splicing into /dev/null: %v (close R %d '%v', close W %d '%v')"
,
err
,
p
.
r
,
errR
,
p
.
w
,
errW
)
}
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/pool.go
deleted
100644 → 0
View file @
e3e61d67
// 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
(
"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
()
}
// Done returns the 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
(
pp
*
pairPool
)
clear
()
{
pp
.
Lock
()
for
_
,
p
:=
range
pp
.
unused
{
p
.
Close
()
}
pp
.
unused
=
pp
.
unused
[
:
0
]
pp
.
Unlock
()
}
func
(
pp
*
pairPool
)
used
()
(
n
int
)
{
pp
.
Lock
()
n
=
pp
.
usedCount
pp
.
Unlock
()
return
n
}
func
(
pp
*
pairPool
)
total
()
int
{
pp
.
Lock
()
n
:=
pp
.
usedCount
+
len
(
pp
.
unused
)
pp
.
Unlock
()
return
n
}
func
(
pp
*
pairPool
)
drop
(
p
*
Pair
)
{
p
.
Close
()
pp
.
Lock
()
pp
.
usedCount
--
pp
.
Unlock
()
}
func
(
pp
*
pairPool
)
get
()
(
p
*
Pair
,
err
error
)
{
pp
.
Lock
()
defer
pp
.
Unlock
()
pp
.
usedCount
++
l
:=
len
(
pp
.
unused
)
if
l
>
0
{
p
:=
pp
.
unused
[
l
-
1
]
pp
.
unused
=
pp
.
unused
[
:
l
-
1
]
return
p
,
nil
}
return
newSplicePair
()
}
func
(
pp
*
pairPool
)
done
(
p
*
Pair
)
{
p
.
discard
()
pp
.
Lock
()
pp
.
usedCount
--
pp
.
unused
=
append
(
pp
.
unused
,
p
)
pp
.
Unlock
()
}
func
init
()
{
splicePool
=
newSplicePairPool
()
}
wcfs/vendor/github.com/hanwen/go-fuse/v2/splice/splice.go
deleted
100644 → 0
View file @
e3e61d67
// 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
// We empty pipes by splicing to /dev/null.
var
devNullFD
uintptr
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
()
fd
,
err
:=
syscall
.
Open
(
"/dev/null"
,
os
.
O_WRONLY
,
0
)
if
err
!=
nil
{
log
.
Panicf
(
"splice: %v"
,
err
)
}
devNullFD
=
uintptr
(
fd
)
}
// 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
osPipe
()
(
int
,
int
,
error
)
{
var
fds
[
2
]
int
err
:=
syscall
.
Pipe2
(
fds
[
:
],
syscall
.
O_NONBLOCK
)
return
fds
[
0
],
fds
[
1
],
err
}
func
newSplicePair
()
(
p
*
Pair
,
err
error
)
{
p
=
&
Pair
{}
p
.
r
,
p
.
w
,
err
=
osPipe
()
if
err
!=
nil
{
return
nil
,
err
}
var
errNo
syscall
.
Errno
p
.
size
,
errNo
=
fcntl
(
uintptr
(
p
.
r
),
F_GETPIPE_SZ
,
0
)
if
err
==
syscall
.
EINVAL
{
p
.
size
=
DefaultPipeSize
return
p
,
nil
}
if
errNo
!=
0
{
p
.
Close
()
return
nil
,
fmt
.
Errorf
(
"fcntl getsize: %v"
,
errNo
)
}
return
p
,
nil
}
wcfs/vendor/modules.txt
View file @
153eda7c
...
...
@@ -11,10 +11,6 @@ github.com/fsnotify/fsnotify
github.com/golang/glog
# github.com/hanwen/go-fuse/v2 v2.0.3 => lab.nexedi.com/kirr/go-fuse/v2 v2.0.0-20200916080003-8c439061f8c9
## explicit
github.com/hanwen/go-fuse/v2/fuse
github.com/hanwen/go-fuse/v2/fuse/nodefs
github.com/hanwen/go-fuse/v2/internal/utimens
github.com/hanwen/go-fuse/v2/splice
# github.com/johncgriffin/overflow v0.0.0-20170615021017-4d914c927216
## explicit
github.com/johncgriffin/overflow
...
...
@@ -94,3 +90,4 @@ lab.nexedi.com/kirr/neo/go/zodb/storage/fs1
lab.nexedi.com/kirr/neo/go/zodb/storage/fs1/fsb
lab.nexedi.com/kirr/neo/go/zodb/storage/zeo
lab.nexedi.com/kirr/neo/go/zodb/wks
# github.com/hanwen/go-fuse/v2 v2.0.3 => lab.nexedi.com/kirr/go-fuse/v2 v2.0.0-20200916080003-8c439061f8c9
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment