1
0
mirror of https://github.com/winfsp/cgofuse.git synced 2025-04-18 23:04:00 +03:00

FUSE3 support

This commit is contained in:
Bill Zissimopoulos 2025-01-04 13:32:57 +00:00
parent 1bbc1acbce
commit a40e268cc9
17 changed files with 526 additions and 380 deletions

View File

@ -31,6 +31,7 @@ build_script:
- go version
- go build -v ./...
- go build -v ./examples/memfs
- go build -tags=memfs3 -v -o memfs3.exe ./examples/memfs
test_script:
- go test -v ./fuse
@ -43,6 +44,7 @@ test_script:
# hard code fsreg parameters because appveyor does not like percents ("--VolumePrefix=%1 %2")
- C:\projects\winfsp\tools\fsreg.bat gomemfs "C:\projects\go\src\github.com\winfsp\cgofuse\memfs.exe" "--VolumePrefix=\gomemfs\share M:" "D:P(A;;RPWPLC;;;WD)"
- C:\projects\winfsp\tools\fsreg.bat gomemfs3 "C:\projects\go\src\github.com\winfsp\cgofuse\memfs3.exe" "--VolumePrefix=\gomemfs3\share N:" "D:P(A;;RPWPLC;;;WD)"
# test against WinFsp v1.0
- 'net use M: \\gomemfs\share'
@ -52,6 +54,13 @@ test_script:
# - C:\Projects\winfsp\ext\test\fstools\src\fsx\fsx.exe -N 10000 test xxxxxx
- 'C: & cd'
- 'net use M: /delete'
- 'net use N: \\gomemfs3\share'
- 'N: & cd'
- C:\projects\winfsp\build\VStudio\build\Release\winfsp-tests-x64.exe --external --resilient --share-prefix=\gomemfs3\share -create_allocation_test -create_fileattr_test -getfileinfo_name_test -setfileinfo_test -delete_access_test -setsecurity_test -querydir_namelen_test -reparse* -stream*
# disable fsx test on WinFsp v1.0, as there was a bug in FUSE write.
# - C:\Projects\winfsp\ext\test\fstools\src\fsx\fsx.exe -N 10000 test xxxxxx
- 'C: & cd'
- 'net use N: /delete'
# test against WinFsp v1.2 DLL with chflags, setcrtime and setchgtime
# HACK: mixing DLL and FSD versions; do not try this at home
@ -63,3 +72,9 @@ test_script:
- C:\Projects\winfsp\ext\test\fstools\src\fsx\fsx.exe -N 10000 test xxxxxx
- 'C: & cd'
- 'net use M: /delete'
- 'net use N: \\gomemfs3\share'
- 'N: & cd'
- C:\projects\winfsp\build\VStudio\build\Release\winfsp-tests-x64.exe --external --resilient --share-prefix=\gomemfs3\share -create_allocation_test -create_fileattr_test -getfileinfo_name_test -delete_access_test -setsecurity_test -querydir_namelen_test -reparse* -stream*
- C:\Projects\winfsp\ext\test\fstools\src\fsx\fsx.exe -N 10000 test xxxxxx
- 'C: & cd'
- 'net use N: /delete'

View File

@ -15,20 +15,27 @@ jobs:
GOARCH: ${{ matrix.arch }}
CGO_ENABLED: ${{ matrix.cgo }}
CPATH: ${{ matrix.cpath }}
GOEXPERIMENT: cgocheck2
GODEBUG: cgocheck=2
strategy:
matrix:
include:
- os: windows-latest
arch: amd64
exe: .exe
cgo: 1
cpath: C:\Program Files (x86)\WinFsp\inc\fuse
- os: windows-latest
arch: amd64
exe: .exe
cgo: 0
- os: windows-latest
arch: 386
exe: .exe
cgo: 0
- os: ubuntu-latest
arch: amd64
cgo: 1
# macOS runner can no longer load the macfuse kext; use runner only to build
- os: macos-latest
arch: amd64
cgo: 1
@ -43,18 +50,14 @@ jobs:
- name: Install go
uses: actions/setup-go@v5
with:
go-version: '1.23'
go-version: 1.20.*
- name: Install winfsp and winfsp-tests (Windows)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: runner.os == 'Windows'
run: |
$headers = @{
Authorization = "token $env:GITHUB_TOKEN"
"User-Agent" = "GitHub Actions"
Authorization = "token ${{ secrets.GITHUB_TOKEN }}"
}
$releases = Invoke-WebRequest https://api.github.com/repos/winfsp/winfsp/releases -Headers $headers | `
ConvertFrom-Json
@ -88,26 +91,43 @@ jobs:
rm -rf secfs.test/fstest/fstest/tests/xacl
rm -rf secfs.test/fstest/fstest/tests/zzz_ResourceFork
- name: Install FUSE (macOS)
- name: Install FUSE and secfs.test
if: runner.os == 'macOS'
run: |
brew install macfuse
- name: Build packages with fuse2
git clone -q https://github.com/billziss-gh/secfs.test.git secfs.test
git -C secfs.test checkout -q edf5eb4a108bfb41073f765aef0cdd32bb3ee1ed
mkdir -p secfs.test/tools/bin
touch secfs.test/tools/bin/bonnie++
touch secfs.test/tools/bin/iozone
make -C secfs.test
# configure fstest for cgofuse
sed -e 's/^fs=.*$/fs="cgofuse"/' -i "" secfs.test/fstest/fstest/tests/conf
# monkey-patch/disable some tests for macOS
rm secfs.test/fstest/fstest/tests/rmdir/12.t
sed -e 's/lchmod)/lchmod) return 1/' -i "" secfs.test/fstest/fstest/tests/misc.sh
# remove irrelevant tests
rm -rf secfs.test/fstest/fstest/tests/xacl
rm -rf secfs.test/fstest/fstest/tests/zzz_ResourceFork
- name: Build packages with FUSE2
run: |
go build -v -o . ./...
- name: Test packages with fuse2
if: runner.os == 'Linux' || runner.os == 'Windows'
run: |
go test -v -count=1 ./fuse
go build -tags=memfs3 -v -o memfs3${{ matrix.exe }} ./examples/memfs
- name: Test file systems (Windows) with fuse2
- name: Test file systems with FUSE2 (Windows)
if: runner.os == 'Windows'
run: |
Set-PSDebug -Trace 1
go test -v -count=1 ./fuse
$testexe = (Get-Item winfsp-tests\winfsp-tests-x64.exe)
Start-Process -NoNewWindow .\memfs.exe "-o uid=-1,rellinks,FileInfoTimeout=-1 X:"
Start-Sleep 3
Push-Location X:\
@ -120,11 +140,25 @@ jobs:
Start-Sleep 3
Pop-Location
- name: Test file systems (Linux) with fuse2
if: runner.os == 'Linux'
Start-Process -NoNewWindow .\memfs3.exe "-o uid=-1,rellinks,FileInfoTimeout=-1 X:"
Start-Sleep 3
Push-Location X:\
. $testexe --fuse-external --resilient --case-insensitive-cmp `
+* `
-create_fileattr_test `
-reparse_nfs_test `
-ea*
Stop-Process -Name memfs3
Start-Sleep 3
Pop-Location
- name: Test file systems (Linux / macOS disabled) with FUSE2
if: runner.os == 'Linux' || (false && runner.os == 'macOS')
run: |
set -x
go test -v -count=1 ./fuse
mkdir p mnt
sudo ./memfs -o allow_other,default_permissions,use_ino,attr_timeout=0 mnt &
@ -134,6 +168,13 @@ jobs:
(cd mnt && ../secfs.test/tools/bin/fsx -e -N 1000 test xxxx)
sudo umount mnt
sudo ./memfs3 -o allow_other,default_permissions,use_ino,attr_timeout=0 mnt &
sleep 3
(cd mnt && sudo prove -fr ../secfs.test/fstest/fstest/tests)
(cd mnt && ../secfs.test/tools/bin/fsx -N 10000 test xxxxxx)
(cd mnt && ../secfs.test/tools/bin/fsx -e -N 1000 test xxxx)
sudo umount mnt
sudo ./passthrough -o allow_other,default_permissions,use_ino,attr_timeout=0 p mnt &
sleep 3
(cd mnt && sudo prove -fr ../secfs.test/fstest/fstest/tests)
@ -143,17 +184,19 @@ jobs:
rm -rf p
rmdir mnt
- name: Build packages with fuse3 (Linux)
- name: Build packages with FUSE3 (Linux)
if: runner.os == 'Linux'
run: |
go build -tags=fuse3 -v -o . ./...
go test -v -count=1 ./fuse
go build -tags=fuse3,memfs3 -v -o memfs3${{ matrix.exe }} ./examples/memfs
- name: Test file systems (Linux) with fuse3
- name: Test file systems with FUSE3 (Linux)
if: runner.os == 'Linux'
run: |
set -x
go test -tags=fuse3 -v -count=1 ./fuse
mkdir p mnt
sudo ./memfs -o allow_other,default_permissions,attr_timeout=0 mnt &
@ -163,6 +206,13 @@ jobs:
(cd mnt && ../secfs.test/tools/bin/fsx -e -N 1000 test xxxx)
sudo umount mnt
sudo ./memfs3 -o allow_other,default_permissions,attr_timeout=0 mnt &
sleep 3
(cd mnt && sudo prove -fr ../secfs.test/fstest/fstest/tests)
(cd mnt && ../secfs.test/tools/bin/fsx -N 10000 test xxxxxx)
(cd mnt && ../secfs.test/tools/bin/fsx -e -N 1000 test xxxx)
sudo umount mnt
sudo ./passthrough -o allow_other,default_permissions,attr_timeout=0 p mnt &
sleep 3
(cd mnt && sudo prove -fr ../secfs.test/fstest/fstest/tests)

View File

@ -64,7 +64,8 @@ func (self *Hellofs) Read(path string, buff []byte, ofst int64, fh uint64) (n in
func (self *Hellofs) Readdir(path string,
fill func(name string, stat *fuse.Stat_t, ofst int64) bool,
ofst int64, fh uint64) (errc int) {
ofst int64,
fh uint64) (errc int) {
fill(".", nil, 0)
fill("..", nil, 0)
fill(filename, nil, 0)

View File

@ -231,7 +231,7 @@ func (self *Memfs) Utimens(path string, tmsp []fuse.Timespec) (errc int) {
return -fuse.ENOENT
}
node.stat.Ctim = fuse.Now()
if tmsp == nil || (len(tmsp) == 2 && tmsp[0].Sec == 0 && tmsp[1].Sec == 0) {
if nil == tmsp {
tmsp0 := node.stat.Ctim
tmsa := [2]fuse.Timespec{tmsp0, tmsp0}
tmsp = tmsa[:]
@ -244,7 +244,7 @@ func (self *Memfs) Utimens(path string, tmsp []fuse.Timespec) (errc int) {
func (self *Memfs) Open(path string, flags int) (errc int, fh uint64) {
defer trace(path, flags)(&errc, &fh)
defer self.synchronize()()
return self.openNode(path, false, flags)
return self.openNode(path, false)
}
func (self *Memfs) Getattr(path string, stat *fuse.Stat_t, fh uint64) (errc int) {
@ -320,7 +320,7 @@ func (self *Memfs) Release(path string, fh uint64) (errc int) {
func (self *Memfs) Opendir(path string) (errc int, fh uint64) {
defer trace(path)(&errc, &fh)
defer self.synchronize()()
return self.openNode(path, true, 0)
return self.openNode(path, true)
}
func (self *Memfs) Readdir(path string,
@ -526,7 +526,7 @@ func (self *Memfs) removeNode(path string, dir bool) int {
return 0
}
func (self *Memfs) openNode(path string, dir bool, flags int) (int, uint64) {
func (self *Memfs) openNode(path string, dir bool) (int, uint64) {
_, _, node := self.lookupNode(path, nil)
if nil == node {
return -fuse.ENOENT, ^uint64(0)
@ -537,13 +537,6 @@ func (self *Memfs) openNode(path string, dir bool, flags int) (int, uint64) {
if dir && fuse.S_IFDIR != node.stat.Mode&fuse.S_IFMT {
return -fuse.ENOTDIR, ^uint64(0)
}
if flags&fuse.O_TRUNC == fuse.O_TRUNC {
node.data = resize(node.data, 0, true)
node.stat.Size = 0
tmsp := fuse.Now()
node.stat.Ctim = tmsp
node.stat.Mtim = tmsp
}
node.opencnt++
if 1 == node.opencnt {
self.openmap[node.stat.Ino] = node
@ -553,12 +546,9 @@ func (self *Memfs) openNode(path string, dir bool, flags int) (int, uint64) {
func (self *Memfs) closeNode(fh uint64) int {
node := self.openmap[fh]
if node == nil {
return -fuse.EBADF
}
node.opencnt--
if 0 == node.opencnt {
delete(self.openmap, fh)
delete(self.openmap, node.stat.Ino)
}
return 0
}
@ -596,6 +586,6 @@ func main() {
memfs := NewMemfs()
host := fuse.NewFileSystemHost(memfs)
host.SetCapReaddirPlus(true)
host.SetUseIno(true)
host.SetUseIno(true) // FUSE3 only
host.Mount("", os.Args[1:])
}

108
examples/memfs/memfs3.go Normal file
View File

@ -0,0 +1,108 @@
//go:build memfs3
// +build memfs3
/*
* memfs3.go
*
* Copyright 2017-2022 Bill Zissimopoulos
*/
/*
* This file is part of Cgofuse.
*
* It is licensed under the MIT license. The full license text can be found
* in the License.txt file at the root of this project.
*/
package main
import (
"github.com/winfsp/cgofuse/fuse"
)
func (self *Memfs) Rename3(oldpath string, newpath string, flags uint32) (errc int) {
defer trace(oldpath, newpath)(&errc)
defer self.synchronize()()
if 0 != flags&^fuse.RENAME_NOREPLACE {
// we only support NOREPLACE
return -fuse.EINVAL
}
oldprnt, oldname, oldnode := self.lookupNode(oldpath, nil)
if nil == oldnode {
return -fuse.ENOENT
}
newprnt, newname, newnode := self.lookupNode(newpath, oldnode)
if nil == newprnt {
return -fuse.ENOENT
}
if "" == newname {
// guard against directory loop creation
return -fuse.EINVAL
}
if oldprnt == newprnt && oldname == newname {
return 0
}
if nil != newnode {
if fuse.RENAME_NOREPLACE == flags&fuse.RENAME_NOREPLACE {
return -fuse.EEXIST
}
errc = self.removeNode(newpath, fuse.S_IFDIR == oldnode.stat.Mode&fuse.S_IFMT)
if 0 != errc {
return errc
}
}
delete(oldprnt.chld, oldname)
newprnt.chld[newname] = oldnode
return 0
}
func (self *Memfs) Chmod3(path string, mode uint32, fh uint64) (errc int) {
defer trace(path, mode, fh)(&errc)
defer self.synchronize()()
node := self.getNode(path, fh)
if nil == node {
return -fuse.ENOENT
}
node.stat.Mode = (node.stat.Mode & fuse.S_IFMT) | mode&07777
node.stat.Ctim = fuse.Now()
return 0
}
func (self *Memfs) Chown3(path string, uid uint32, gid uint32, fh uint64) (errc int) {
defer trace(path, uid, gid, fh)(&errc)
defer self.synchronize()()
node := self.getNode(path, fh)
if nil == node {
return -fuse.ENOENT
}
if ^uint32(0) != uid {
node.stat.Uid = uid
}
if ^uint32(0) != gid {
node.stat.Gid = gid
}
node.stat.Ctim = fuse.Now()
return 0
}
func (self *Memfs) Utimens3(path string, tmsp []fuse.Timespec, fh uint64) (errc int) {
defer trace(path, tmsp, fh)(&errc)
defer self.synchronize()()
node := self.getNode(path, fh)
if nil == node {
return -fuse.ENOENT
}
node.stat.Ctim = fuse.Now()
if nil == tmsp {
tmsp0 := node.stat.Ctim
tmsa := [2]fuse.Timespec{tmsp0, tmsp0}
tmsp = tmsa[:]
}
node.stat.Atim = tmsp[0]
node.stat.Mtim = tmsp[1]
return 0
}
var _ fuse.FileSystemRename3 = (*Memfs)(nil)
var _ fuse.FileSystemChmod3 = (*Memfs)(nil)
var _ fuse.FileSystemChown3 = (*Memfs)(nil)
var _ fuse.FileSystemRename3 = (*Memfs)(nil)

View File

@ -1,4 +1,3 @@
//go:build darwin || freebsd || netbsd || openbsd || linux
// +build darwin freebsd netbsd openbsd linux
/*
@ -265,6 +264,6 @@ func main() {
args = append(args[:len(args)-2], args[len(args)-1])
}
_host = fuse.NewFileSystemHost(&ptfs)
_host.SetUseIno(true)
_host.SetUseIno(true) // FUSE3 only
_host.Mount("", args[1:])
}

View File

@ -1,4 +1,3 @@
//go:build darwin
// +build darwin
/*

View File

@ -1,4 +1,3 @@
//go:build freebsd
// +build freebsd
/*

View File

@ -1,4 +1,3 @@
//go:build linux
// +build linux
/*

View File

@ -1,4 +1,3 @@
//go:build netbsd
// +build netbsd
/*

View File

@ -1,4 +1,3 @@
//go:build openbsd
// +build openbsd
/*

View File

@ -313,25 +313,6 @@ type FileSystemInterface interface {
Listxattr(path string, fill func(name string) bool) int
}
// FileSystemFuse3 is the interface that wraps the fuse3 equivalent methods.
//
// ChmodFuse3, ChownFuse3, and UtimensFuse3 each similar to Chmod, Chown, and
// Utimens except they include a file handle that could be null and only work
// on with Fuse3.
//
// RenameFuse3 and ReaddirFuse3 are similar to Rename and Readir except that they
// include additional flags.
type FileSystemFuse3 interface {
ChmodFuse3(path string, mode uint32, fh uint64) int
ChownFuse3(path string, uid uint32, gid uint32, fh uint64) int
UtimensFuse3(path string, tmsp []Timespec, fh uint64) int
RenameFuse3(oldpath string, newpath string, flags uint32) int
ReaddirFuse3(path string,
fill func(name string, stat *Stat_t, ofst int64) bool,
ofst int64,
fh uint64, flags uint32) int
}
// FileSystemOpenEx is the interface that wraps the OpenEx and CreateEx methods.
//
// OpenEx and CreateEx are similar to Open and Create except that they allow
@ -370,6 +351,38 @@ type FileSystemSetchgtime interface {
Setchgtime(path string, tmsp Timespec) int
}
// FileSystemChmod3 is the interface that wraps the FUSE3 Chmod method.
//
// Chmod3 is similar to Chmod except that it includes a file handle that is
// available only under FUSE3.
type FileSystemChmod3 interface {
Chmod3(path string, mode uint32, fh uint64) int
}
// FileSystemChown3 is the interface that wraps the FUSE3 Chown method.
//
// Chown3 is similar to Chown except that it includes a file handle that is
// available only under FUSE3.
type FileSystemChown3 interface {
Chown3(path string, uid uint32, gid uint32, fh uint64) int
}
// FileSystemUtimens3 is the interface that wraps the FUSE3 Utimens method.
//
// Utimens3 is similar to Utimens except that it includes a file handle that is
// available only under FUSE3.
type FileSystemUtimens3 interface {
Utimens3(path string, tmsp []Timespec, fh uint64) int
}
// FileSystemRename3 is the interface that wraps the FUSE3 Rename method.
//
// Rename3 is similar to Rename except that it includes flags that are
// available only under FUSE3.
type FileSystemRename3 interface {
Rename3(oldpath string, newpath string, flags uint32) int
}
// Error encapsulates a FUSE error code. In some rare circumstances it is useful
// to signal an error to the FUSE layer by boxing the error code using Error and
// calling panic(). The FUSE layer will recover and report the boxed error code

View File

@ -303,6 +303,19 @@ const (
XATTR_REPLACE = int(C.XATTR_REPLACE)
)
// Flags used in Utimens and Utimens3.
const (
UTIME_NOW = (1 << 30) - 1
UTIME_OMIT = (1 << 30) - 2
)
// Flags used in FileSystemRename3.Rename3.
const (
RENAME_NOREPLACE = 1 << 0
RENAME_EXCHANGE = 1 << 1
RENAME_WHITEOUT = 1 << 2
)
// Notify actions.
const (
NOTIFY_MKDIR = 0x0001

View File

@ -161,6 +161,19 @@ const (
XATTR_REPLACE = 2
)
// Flags used in Utimens and Utimens3.
const (
UTIME_NOW = (1 << 30) - 1
UTIME_OMIT = (1 << 30) - 2
)
// Flags used in FileSystemRename3.Rename3.
const (
RENAME_NOREPLACE = 1 << 0
RENAME_EXCHANGE = 1 << 1
RENAME_WHITEOUT = 1 << 2
)
// Notify actions.
const (
NOTIFY_MKDIR = 0x0001

View File

@ -31,8 +31,12 @@ type FileSystemHost struct {
mntp string
sigc chan os.Signal
capCaseInsensitive, capReaddirPlus, capDeleteAccess bool
directIO, useIno bool
capCaseInsensitive bool
capReaddirPlus bool
capDeleteAccess bool
capOpenTrunc bool
directIO bool
useIno bool
}
var (
@ -112,8 +116,7 @@ func recoverAsErrno(errc0 *c_int) {
}
}
func hostGetattr(path0 *c_char, stat0 *c_fuse_stat_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
func hostGetattr(path0 *c_char, stat0 *c_fuse_stat_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
path := c_GoString(path0)
@ -185,11 +188,15 @@ func hostRename(oldpath0 *c_char, newpath0 *c_char, flags c_uint32_t) (errc0 c_i
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
oldpath, newpath := c_GoString(oldpath0), c_GoString(newpath0)
intf, ok := fsop.(FileSystemFuse3)
intf, ok := fsop.(FileSystemRename3)
if ok {
errc := intf.RenameFuse3(oldpath, newpath, uint32(flags))
errc := intf.Rename3(oldpath, newpath, uint32(flags))
return c_int(errc)
} else {
if 0 != flags {
// man 2 rename: EINVAL when "the filesystem does not support one of the flags"
return -c_int(EINVAL)
}
errc := fsop.Rename(oldpath, newpath)
return c_int(errc)
}
@ -207,13 +214,13 @@ func hostChmod(path0 *c_char, mode0 c_fuse_mode_t, fi0 *c_struct_fuse_file_info)
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
path := c_GoString(path0)
intf, ok := fsop.(FileSystemFuse3)
intf, ok := fsop.(FileSystemChmod3)
if ok {
fifh := ^uint64(0)
if nil != fi0 {
fifh = uint64(fi0.fh)
}
errc := intf.ChmodFuse3(path, uint32(mode0), fifh)
errc := intf.Chmod3(path, uint32(mode0), fifh)
return c_int(errc)
} else {
errc := fsop.Chmod(path, uint32(mode0))
@ -225,13 +232,13 @@ func hostChown(path0 *c_char, uid0 c_fuse_uid_t, gid0 c_fuse_gid_t, fi0 *c_struc
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
path := c_GoString(path0)
intf, ok := fsop.(FileSystemFuse3)
intf, ok := fsop.(FileSystemChown3)
if ok {
fifh := ^uint64(0)
if nil != fi0 {
fifh = uint64(fi0.fh)
}
errc := intf.ChownFuse3(path, uint32(uid0), uint32(gid0), fifh)
errc := intf.Chown3(path, uint32(uid0), uint32(gid0), fifh)
return c_int(errc)
} else {
errc := fsop.Chown(path, uint32(uid0), uint32(gid0))
@ -411,7 +418,7 @@ func hostOpendir(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
}
func hostReaddir(path0 *c_char, buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, ofst0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info, flags c_fuse_readdir_flags_t) (errc0 c_int) {
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
path := c_GoString(path0)
@ -427,14 +434,8 @@ func hostReaddir(path0 *c_char, buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, o
return 0 == c_hostFilldir(fill0, buff0, name, stat, c_fuse_off_t(off1))
}
}
intf, ok := fsop.(FileSystemFuse3)
if ok {
errc := intf.ReaddirFuse3(path, fill, int64(ofst0), uint64(fi0.fh), uint32(flags))
return c_int(errc)
} else {
errc := fsop.Readdir(path, fill, int64(ofst0), uint64(fi0.fh))
return c_int(errc)
}
errc := fsop.Readdir(path, fill, int64(ofst0), uint64(fi0.fh))
return c_int(errc)
}
func hostReleasedir(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
@ -456,7 +457,7 @@ func hostFsyncdir(path0 *c_char, datasync c_int, fi0 *c_struct_fuse_file_info) (
return c_int(errc)
}
func hostInit(conn0 *c_struct_fuse_conn_info, cfg *c_struct_fuse_config) (user_data unsafe.Pointer) {
func hostInit(conn0 *c_struct_fuse_conn_info, conf0 *c_struct_fuse_config) (user_data unsafe.Pointer) {
defer func() {
recover()
}()
@ -467,8 +468,9 @@ func hostInit(conn0 *c_struct_fuse_conn_info, cfg *c_struct_fuse_config) (user_d
c_hostAsgnCconninfo(conn0,
c_bool(host.capCaseInsensitive),
c_bool(host.capReaddirPlus),
c_bool(host.capDeleteAccess))
c_hostAsgnCconfig(cfg,
c_bool(host.capDeleteAccess),
c_bool(host.capOpenTrunc))
c_hostAsgnCconfig(conf0,
c_bool(host.directIO),
c_bool(host.useIno))
if nil != host.sigc {
@ -557,35 +559,29 @@ func hostUtimens(path0 *c_char, tmsp0 *c_fuse_timespec_t, fi0 *c_struct_fuse_fil
defer recoverAsErrno(&errc0)
fsop := hostHandleGet(c_fuse_get_context().private_data).fsop
path := c_GoString(path0)
intf, ok := fsop.(FileSystemFuse3)
tmsp := [2]Timespec{}
if nil == tmsp0 {
tmsp[0] = Now()
tmsp[1] = tmsp[0]
} else if tmsa := (*[2]c_fuse_timespec_t)(unsafe.Pointer(tmsp0)); UTIME_NOW == tmsa[0].tv_nsec &&
UTIME_NOW == tmsa[1].tv_nsec {
tmsp[0] = Now()
tmsp[1] = tmsp[0]
} else {
copyFusetimespecFromCtimespec(&tmsp[0], &tmsa[0])
copyFusetimespecFromCtimespec(&tmsp[1], &tmsa[1])
}
intf, ok := fsop.(FileSystemUtimens3)
if ok {
fifh := ^uint64(0)
if nil != fi0 {
fifh = uint64(fi0.fh)
}
if tmsp0 == nil {
errc := intf.UtimensFuse3(path, nil, fifh)
return c_int(errc)
} else {
tmsp := [2]Timespec{}
tmsa := (*[2]c_fuse_timespec_t)(unsafe.Pointer(tmsp0))
copyFusetimespecFromCtimespec(&tmsp[0], &tmsa[0])
copyFusetimespecFromCtimespec(&tmsp[1], &tmsa[1])
errc := intf.UtimensFuse3(path, tmsp[:], fifh)
return c_int(errc)
}
errc := intf.Utimens3(path, tmsp[:], fifh)
return c_int(errc)
} else {
if tmsp0 == nil {
errc := fsop.Utimens(path, nil)
return c_int(errc)
} else {
tmsp := [2]Timespec{}
tmsa := (*[2]c_fuse_timespec_t)(unsafe.Pointer(tmsp0))
copyFusetimespecFromCtimespec(&tmsp[0], &tmsa[0])
copyFusetimespecFromCtimespec(&tmsp[1], &tmsa[1])
errc := fsop.Utimens(path, tmsp[:])
return c_int(errc)
}
errc := fsop.Utimens(path, tmsp[:])
return c_int(errc)
}
}
@ -682,13 +678,19 @@ func (host *FileSystemHost) SetCapDeleteAccess(value bool) {
host.capDeleteAccess = value
}
// SetDirectIO causes the file system to disable page caching [Fuse3 only]. Must be set
// SetCapOpenTrunc informs the host that the hosted file system can handle the O_TRUNC
// Open flag [Linux only].
func (host *FileSystemHost) SetCapOpenTrunc(value bool) {
host.capOpenTrunc = value
}
// SetDirectIO causes the file system to disable page caching [FUSE3 only]. Must be set
// before Mount is called.
func (host *FileSystemHost) SetDirectIO(value bool) {
host.directIO = value
}
// SetUseIno causes the file system to use its own inode values [Fuse3 only]. Must be set
// SetUseIno causes the file system to use its own inode values [FUSE3 only]. Must be set
// before Mount is called.
func (host *FileSystemHost) SetUseIno(value bool) {
host.useIno = value
@ -699,10 +701,10 @@ func (host *FileSystemHost) SetUseIno(value bool) {
// Many of the mount options in opts are specific to the underlying FUSE implementation.
// Some of the common options include:
//
// -h --help print help
// -V --version print FUSE version
// -d -o debug enable FUSE debug output
// -s disable multi-threaded operation
// -h --help print help
// -V --version print FUSE version
// -d -o debug enable FUSE debug output
// -s disable multi-threaded operation
//
// Please refer to the individual FUSE implementation documentation for additional options.
//
@ -912,48 +914,49 @@ func optNormStr(opt string) string {
//
// For pointer to bool types:
//
// -x Match -x without parameter.
// -foo --foo As above for -foo or --foo.
// foo Match "-o foo".
// -x= -foo= --foo= foo= Match option with parameter.
// -x=%VERB ... foo=%VERB Match option with parameter of syntax.
// Allowed verbs: d,o,x,X,v
// - d,o,x,X: set to true if parameter non-0.
// - v: set to true if parameter present.
// -x Match -x without parameter.
// -foo --foo As above for -foo or --foo.
// foo Match "-o foo".
// -x= -foo= --foo= foo= Match option with parameter.
// -x=%VERB ... foo=%VERB Match option with parameter of syntax.
// Allowed verbs: d,o,x,X,v
// - d,o,x,X: set to true if parameter non-0.
// - v: set to true if parameter present.
//
// The formats -x=, and -x=%v are equivalent.
// The formats -x=, and -x=%v are equivalent.
//
// For pointer to other types:
//
// -x Match -x with parameter (-x=PARAM).
// -foo --foo As above for -foo or --foo.
// foo Match "-o foo=PARAM".
// -x= -foo= --foo= foo= Match option with parameter.
// -x=%VERB ... foo=%VERB Match option with parameter of syntax.
// Allowed verbs for pointer to int types: d,o,x,X,v
// Allowed verbs for pointer to string types: s,v
// -x Match -x with parameter (-x=PARAM).
// -foo --foo As above for -foo or --foo.
// foo Match "-o foo=PARAM".
// -x= -foo= --foo= foo= Match option with parameter.
// -x=%VERB ... foo=%VERB Match option with parameter of syntax.
// Allowed verbs for pointer to int types: d,o,x,X,v
// Allowed verbs for pointer to string types: s,v
//
// The formats -x, -x=, and -x=%v are equivalent.
// The formats -x, -x=, and -x=%v are equivalent.
//
// For example:
//
// var f bool
// var set_attr_timeout bool
// var attr_timeout int
// var umask uint32
// outargs, err := OptParse(args, "-f attr_timeout= attr_timeout umask=%o",
// &f, &set_attr_timeout, &attr_timeout, &umask)
// var f bool
// var set_attr_timeout bool
// var attr_timeout int
// var umask uint32
// outargs, err := OptParse(args, "-f attr_timeout= attr_timeout umask=%o",
// &f, &set_attr_timeout, &attr_timeout, &umask)
//
// Will accept a command line of:
//
// $ program -f -o attr_timeout=42,umask=077
// $ program -f -o attr_timeout=42,umask=077
//
// And will set variables as follows:
//
// f == true
// set_attr_timeout == true
// attr_timeout == 42
// umask == 077
// f == true
// set_attr_timeout == true
// attr_timeout == 42
// umask == 077
//
func OptParse(args []string, format string, vals ...interface{}) (outargs []string, err error) {
if 0 == c_hostFuseInit() {
if "windows" == runtime.GOOS {

View File

@ -16,18 +16,14 @@
package fuse
/*
#cgo fuse3,freebsd CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/fuse3
#cgo fuse3,netbsd CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64 -D_KERNTYPES
#cgo fuse3,openbsd CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64
#cgo fuse3,linux CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
#cgo fuse3,linux LDFLAGS: -lfuse3 -ldl
#cgo darwin CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/osxfuse/fuse -I/usr/local/include/fuse
#cgo !fuse3,freebsd CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/fuse
#cgo !fuse3,netbsd CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -D_KERNTYPES
#cgo !fuse3,openbsd CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64
#cgo !fuse3,linux CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
#cgo !fuse3,linux LDFLAGS: -ldl
#cgo freebsd,!fuse3 CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/fuse
#cgo freebsd,fuse3 CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64 -I/usr/local/include/fuse3
#cgo netbsd CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -D_KERNTYPES
#cgo openbsd CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64
#cgo linux,!fuse3 CFLAGS: -DFUSE_USE_VERSION=28 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
#cgo linux,fuse3 CFLAGS: -DFUSE_USE_VERSION=39 -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse3
#cgo linux LDFLAGS: -ldl
#cgo windows CFLAGS: -DFUSE_USE_VERSION=28 -I/usr/local/include/winfsp
// Use `set CPATH=C:\Program Files (x86)\WinFsp\inc\fuse` on Windows.
// The flag `I/usr/local/include/winfsp` only works on xgo and docker.
@ -120,11 +116,7 @@ static void cgofuse_init_fail(void)
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__linux__)
#if FUSE_USE_VERSION >= 30
#include <fuse3/fuse.h>
#else
#include <fuse.h>
#endif
#include <fuse.h>
#if defined(__OpenBSD__)
static int (*pfn_fuse_main)(int argc, char *argv[],
@ -185,28 +177,20 @@ static void *cgofuse_init_fuse(void)
if (0 == h)
h = dlopen("/usr/local/lib/libfuse-t.dylib", RTLD_NOW); // FUSE-T
#elif defined(__FreeBSD__)
#if FUSE_USE_VERSION >= 30
h = dlopen("libfuse3.so.3", RTLD_NOW);
#if FUSE_USE_VERSION < 30
h = dlopen("libfuse.so.2", RTLD_NOW);
#else
h = dlopen("libfuse.so.2", RTLD_NOW);
h = dlopen("libfuse3.so.3", RTLD_NOW);
#endif
#elif defined(__NetBSD__)
#if FUSE_USE_VERSION >= 30
h = dlopen("libfuse3.so.3", RTLD_NOW);
#else
h = dlopen("libfuse.so.2", RTLD_NOW);
#endif
h = dlopen("librefuse.so.2", RTLD_NOW);
#elif defined(__OpenBSD__)
#if FUSE_USE_VERSION >= 30
h = dlopen("libfuse3.so.3", RTLD_NOW);
#else
h = dlopen("libfuse.so.2", RTLD_NOW);
#endif
h = dlopen("libfuse.so.2.0", RTLD_NOW);
#elif defined(__linux__)
#if FUSE_USE_VERSION >= 30
h = dlopen("libfuse3.so.3", RTLD_NOW);
#if FUSE_USE_VERSION < 30
h = dlopen("libfuse.so.2", RTLD_NOW);
#else
h = dlopen("libfuse.so.2", RTLD_NOW);
h = dlopen("libfuse3.so.3", RTLD_NOW);
#endif
#endif
if (0 == h)
@ -347,19 +331,18 @@ typedef struct fuse_timespec fuse_timespec_t;
typedef unsigned int fuse_opt_offset_t;
#endif
#if FUSE_USE_VERSION >= 30
typedef enum fuse_readdir_flags fuse_readdir_flags_t;
typedef enum fuse_fill_dir_flags fuse_fill_dir_flags_t;
static int fill_dir_plus = (1 << 1);
#else
typedef int fuse_readdir_flags_t;
#if FUSE_USE_VERSION < 30
struct fuse_config;
enum fuse_readdir_flags
{
fuse_readdir_flags_DUMMY
};
#endif
#if FUSE_USE_VERSION >= 30
extern int go_hostGetattrFuse3(char *path, fuse_stat_t *stbuf, struct fuse_file_info *fi);
#if FUSE_USE_VERSION < 30
extern int go_hostGetattr(char *path, fuse_stat_t *stbuf);
#else
extern int go_hostGetattrFuse2(char *path, fuse_stat_t *stbuf);
extern int go_hostGetattr3(char *path, fuse_stat_t *stbuf, struct fuse_file_info *fi);
#endif
extern int go_hostReadlink(char *path, char *buf, size_t size);
extern int go_hostMknod(char *path, fuse_mode_t mode, fuse_dev_t dev);
@ -367,20 +350,20 @@ extern int go_hostMkdir(char *path, fuse_mode_t mode);
extern int go_hostUnlink(char *path);
extern int go_hostRmdir(char *path);
extern int go_hostSymlink(char *target, char *newpath);
#if FUSE_USE_VERSION >= 30
extern int go_hostRenameFuse3(char *oldpath, char *newpath, unsigned int flags);
#if FUSE_USE_VERSION < 30
extern int go_hostRename(char *oldpath, char *newpath);
#else
extern int go_hostRenameFuse2(char *oldpath, char *newpath);
extern int go_hostRename3(char *oldpath, char *newpath, unsigned int flags);
#endif
extern int go_hostLink(char *oldpath, char *newpath);
#if FUSE_USE_VERSION >= 30
extern int go_hostChmodFuse3(char *path, fuse_mode_t mode, struct fuse_file_info *fi);
extern int go_hostChownFuse3(char *path, fuse_uid_t uid, fuse_gid_t gid, struct fuse_file_info *fi);
extern int go_hostTruncateFuse3(char *path, fuse_off_t size, struct fuse_file_info *fi);
#if FUSE_USE_VERSION < 30
extern int go_hostChmod(char *path, fuse_mode_t mode);
extern int go_hostChown(char *path, fuse_uid_t uid, fuse_gid_t gid);
extern int go_hostTruncate(char *path, fuse_off_t size);
#else
extern int go_hostChmodFuse2(char *path, fuse_mode_t mode);
extern int go_hostChownFuse2(char *path, fuse_uid_t uid, fuse_gid_t gid);
extern int go_hostTruncateFuse2(char *path, fuse_off_t size);
extern int go_hostChmod3(char *path, fuse_mode_t mode, struct fuse_file_info *fi);
extern int go_hostChown3(char *path, fuse_uid_t uid, fuse_gid_t gid, struct fuse_file_info *fi);
extern int go_hostTruncate3(char *path, fuse_off_t size, struct fuse_file_info *fi);
#endif
extern int go_hostOpen(char *path, struct fuse_file_info *fi);
extern int go_hostRead(char *path, char *buf, size_t size, fuse_off_t off,
@ -396,19 +379,19 @@ extern int go_hostGetxattr(char *path, char *name, char *value, size_t size);
extern int go_hostListxattr(char *path, char *namebuf, size_t size);
extern int go_hostRemovexattr(char *path, char *name);
extern int go_hostOpendir(char *path, struct fuse_file_info *fi);
#if FUSE_USE_VERSION >= 30
extern int go_hostReaddirFuse3(char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
struct fuse_file_info *fi, fuse_readdir_flags_t flags);
#else
extern int go_hostReaddirFuse2(char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
#if FUSE_USE_VERSION < 30
extern int go_hostReaddir(char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
struct fuse_file_info *fi);
#else
extern int go_hostReaddir3(char *path, void *buf, fuse_fill_dir_t filler, fuse_off_t off,
struct fuse_file_info *fi, enum fuse_readdir_flags flags);
#endif
extern int go_hostReleasedir(char *path, struct fuse_file_info *fi);
extern int go_hostFsyncdir(char *path, int datasync, struct fuse_file_info *fi);
#if FUSE_USE_VERSION >= 30
extern void *go_hostInitFuse3(struct fuse_conn_info *conn, struct fuse_config *cfg);
#if FUSE_USE_VERSION < 30
extern void *go_hostInit(struct fuse_conn_info *conn);
#else
extern void *go_hostInitFuse2(struct fuse_conn_info *conn);
extern void *go_hostInit3(struct fuse_conn_info *conn, struct fuse_config *conf);
#endif
extern void go_hostDestroy(void *data);
extern int go_hostAccess(char *path, int mask);
@ -418,10 +401,10 @@ extern int go_hostFtruncate(char *path, fuse_off_t off, struct fuse_file_info *f
extern int go_hostFgetattr(char *path, fuse_stat_t *stbuf, struct fuse_file_info *fi);
#endif
//extern int go_hostLock(char *path, struct fuse_file_info *fi, int cmd, struct fuse_flock *lock);
#if FUSE_USE_VERSION >= 30
extern int go_hostUtimensFuse3(char *path, fuse_timespec_t tv[2], struct fuse_file_info *fi);
#if FUSE_USE_VERSION < 30
extern int go_hostUtimens(char *path, fuse_timespec_t tv[2]);
#else
extern int go_hostUtimensFuse2(char *path, fuse_timespec_t tv[2]);
extern int go_hostUtimens3(char *path, fuse_timespec_t tv[2], struct fuse_file_info *fi);
#endif
extern int go_hostGetpath(char *path, char *buf, size_t size,
struct fuse_file_info *fi);
@ -432,12 +415,20 @@ extern int go_hostChflags(char *path, uint32_t flags);
static inline void hostAsgnCconninfo(struct fuse_conn_info *conn,
bool capCaseInsensitive,
bool capReaddirPlus,
bool capDeleteAccess)
bool capDeleteAccess,
bool capOpenTrunc)
{
#if defined(__APPLE__)
if (capCaseInsensitive)
FUSE_ENABLE_CASE_INSENSITIVE(conn);
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__linux__)
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#elif defined(__linux__)
// FUSE_CAP_ATOMIC_O_TRUNC was disabled in FUSE2 and is enabled in FUSE3.
// So disable it here, unless the user explicitly enables it.
if (capOpenTrunc)
conn->want |= conn->capable & FUSE_CAP_ATOMIC_O_TRUNC;
else
conn->want &= ~FUSE_CAP_ATOMIC_O_TRUNC;
#elif defined(_WIN32)
#if defined(FSP_FUSE_CAP_STAT_EX)
conn->want |= conn->capable & FSP_FUSE_CAP_STAT_EX;
@ -452,21 +443,21 @@ static inline void hostAsgnCconninfo(struct fuse_conn_info *conn,
#endif
}
#if FUSE_USE_VERSION >= 30
static inline void hostAsgnCconfig(struct fuse_config *cfg,
#if FUSE_USE_VERSION < 30
static inline void hostAsgnCconfig(struct fuse_config *conf,
bool direct_io,
bool use_ino)
{
memset(cfg, 0, sizeof *cfg);
cfg->direct_io = direct_io;
cfg->use_ino = use_ino;
cfg->attr_timeout = 0;
}
#else
static inline void hostAsgnCconfig(struct fuse_config *cfg,
static inline void hostAsgnCconfig(struct fuse_config *conf,
bool direct_io,
bool use_ino)
{}
{
memset(conf, 0, sizeof *conf);
conf->direct_io = direct_io;
conf->use_ino = use_ino;
}
#endif
static inline void hostCstatvfsFromFusestatfs(fuse_statvfs_t *stbuf,
@ -581,10 +572,10 @@ static inline void hostAsgnCfileinfo(struct fuse_file_info *fi,
static inline int hostFilldir(fuse_fill_dir_t filler, void *buf,
char *name, fuse_stat_t *stbuf, fuse_off_t off)
{
#if FUSE_USE_VERSION >= 30
return filler(buf, name, stbuf, off, fill_dir_plus);
#else
#if FUSE_USE_VERSION < 30
return filler(buf, name, stbuf, off);
#else
return filler(buf, name, stbuf, off, FUSE_FILL_DIR_PLUS);
#endif
}
@ -627,10 +618,10 @@ static int hostMount(int argc, char *argv[], void *data)
{
static struct fuse_operations fsop =
{
#if FUSE_USE_VERSION >= 30
.getattr = (int (*)(const char *, fuse_stat_t *, struct fuse_file_info *))go_hostGetattrFuse3,
#if FUSE_USE_VERSION < 30
.getattr = (int (*)(const char *, fuse_stat_t *))go_hostGetattr,
#else
.getattr = (int (*)(const char *, fuse_stat_t *))go_hostGetattrFuse2,
.getattr = (int (*)(const char *, fuse_stat_t *, struct fuse_file_info *))go_hostGetattr3,
#endif
.readlink = (int (*)(const char *, char *, size_t))go_hostReadlink,
.mknod = (int (*)(const char *, fuse_mode_t, fuse_dev_t))go_hostMknod,
@ -638,20 +629,20 @@ static int hostMount(int argc, char *argv[], void *data)
.unlink = (int (*)(const char *))go_hostUnlink,
.rmdir = (int (*)(const char *))go_hostRmdir,
.symlink = (int (*)(const char *, const char *))go_hostSymlink,
#if FUSE_USE_VERSION >= 30
.rename = (int (*)(const char *, const char *, unsigned int flags))go_hostRenameFuse3,
#if FUSE_USE_VERSION < 30
.rename = (int (*)(const char *, const char *))go_hostRename,
#else
.rename = (int (*)(const char *, const char *))go_hostRenameFuse2,
.rename = (int (*)(const char *, const char *, unsigned int flags))go_hostRename3,
#endif
.link = (int (*)(const char *, const char *))go_hostLink,
#if FUSE_USE_VERSION >= 30
.chmod = (int (*)(const char *, fuse_mode_t, struct fuse_file_info *))go_hostChmodFuse3,
.chown = (int (*)(const char *, fuse_uid_t, fuse_gid_t, struct fuse_file_info *))go_hostChownFuse3,
.truncate = (int (*)(const char *, fuse_off_t, struct fuse_file_info *))go_hostTruncateFuse3,
#if FUSE_USE_VERSION < 30
.chmod = (int (*)(const char *, fuse_mode_t))go_hostChmod,
.chown = (int (*)(const char *, fuse_uid_t, fuse_gid_t))go_hostChown,
.truncate = (int (*)(const char *, fuse_off_t))go_hostTruncate,
#else
.chmod = (int (*)(const char *, fuse_mode_t))go_hostChmodFuse2,
.chown = (int (*)(const char *, fuse_uid_t, fuse_gid_t))go_hostChownFuse2,
.truncate = (int (*)(const char *, fuse_off_t))go_hostTruncateFuse2,
.chmod = (int (*)(const char *, fuse_mode_t, struct fuse_file_info *))go_hostChmod3,
.chown = (int (*)(const char *, fuse_uid_t, fuse_gid_t, struct fuse_file_info *))go_hostChown3,
.truncate = (int (*)(const char *, fuse_off_t, struct fuse_file_info *))go_hostTruncate3,
#endif
.open = (int (*)(const char *, struct fuse_file_info *))go_hostOpen,
.read = (int (*)(const char *, char *, size_t, fuse_off_t, struct fuse_file_info *))
@ -674,19 +665,19 @@ static int hostMount(int argc, char *argv[], void *data)
.listxattr = (int (*)(const char *, char *, size_t))go_hostListxattr,
.removexattr = (int (*)(const char *, const char *))go_hostRemovexattr,
.opendir = (int (*)(const char *, struct fuse_file_info *))go_hostOpendir,
#if FUSE_USE_VERSION >= 30
#if FUSE_USE_VERSION < 30
.readdir = (int (*)(const char *, void *, fuse_fill_dir_t, fuse_off_t,
struct fuse_file_info *, fuse_readdir_flags_t flags))go_hostReaddirFuse3,
struct fuse_file_info *))go_hostReaddir,
#else
.readdir = (int (*)(const char *, void *, fuse_fill_dir_t, fuse_off_t,
struct fuse_file_info *))go_hostReaddirFuse2,
struct fuse_file_info *, enum fuse_readdir_flags flags))go_hostReaddir3,
#endif
.releasedir = (int (*)(const char *, struct fuse_file_info *))go_hostReleasedir,
.fsyncdir = (int (*)(const char *, int, struct fuse_file_info *))go_hostFsyncdir,
#if FUSE_USE_VERSION >= 30
.init = (void *(*)(struct fuse_conn_info *, struct fuse_config *))go_hostInitFuse3,
#if FUSE_USE_VERSION < 30
.init = (void *(*)(struct fuse_conn_info *))go_hostInit,
#else
.init = (void *(*)(struct fuse_conn_info *))go_hostInitFuse2,
.init = (void *(*)(struct fuse_conn_info *, struct fuse_config *))go_hostInit3,
#endif
.destroy = (void (*)(void *))go_hostDestroy,
.access = (int (*)(const char *, int))go_hostAccess,
@ -697,10 +688,10 @@ static int hostMount(int argc, char *argv[], void *data)
#endif
//.lock = (int (*)(const char *, struct fuse_file_info *, int, struct fuse_flock *))
// go_hostFlock,
#if FUSE_USE_VERSION >= 30
.utimens = (int (*)(const char *, const fuse_timespec_t [2], struct fuse_file_info *))go_hostUtimensFuse3,
#if FUSE_USE_VERSION < 30
.utimens = (int (*)(const char *, const fuse_timespec_t [2]))go_hostUtimens,
#else
.utimens = (int (*)(const char *, const fuse_timespec_t [2]))go_hostUtimensFuse2,
.utimens = (int (*)(const char *, const fuse_timespec_t [2], struct fuse_file_info *))go_hostUtimens3,
#endif
#if defined(__APPLE__) || (defined(_WIN32) && defined(FSP_FUSE_CAP_STAT_EX))
.setchgtime = (int (*)(const char *, const fuse_timespec_t *))go_hostSetchgtime,
@ -829,39 +820,39 @@ import "C"
import "unsafe"
type (
c_bool = C.bool
c_char = C.char
c_fuse_dev_t = C.fuse_dev_t
c_fuse_fill_dir_t = C.fuse_fill_dir_t
c_fuse_gid_t = C.fuse_gid_t
c_fuse_mode_t = C.fuse_mode_t
c_fuse_off_t = C.fuse_off_t
c_fuse_opt_offset_t = C.fuse_opt_offset_t
c_fuse_readdir_flags_t = C.fuse_readdir_flags_t
c_fuse_stat_t = C.fuse_stat_t
c_fuse_stat_ex_t = C.fuse_stat_ex_t
c_fuse_statvfs_t = C.fuse_statvfs_t
c_fuse_timespec_t = C.fuse_timespec_t
c_fuse_uid_t = C.fuse_uid_t
c_int = C.int
c_int16_t = C.int16_t
c_int32_t = C.int32_t
c_int64_t = C.int64_t
c_int8_t = C.int8_t
c_size_t = C.size_t
c_struct_fuse = C.struct_fuse
c_struct_fuse_args = C.struct_fuse_args
c_struct_fuse_config = C.struct_fuse_config
c_struct_fuse_conn_info = C.struct_fuse_conn_info
c_struct_fuse_context = C.struct_fuse_context
c_struct_fuse_file_info = C.struct_fuse_file_info
c_struct_fuse_opt = C.struct_fuse_opt
c_uint16_t = C.uint16_t
c_uint32_t = C.uint32_t
c_uint64_t = C.uint64_t
c_uint8_t = C.uint8_t
c_uintptr_t = C.uintptr_t
c_unsigned = C.unsigned
c_bool = C.bool
c_char = C.char
c_fuse_dev_t = C.fuse_dev_t
c_fuse_fill_dir_t = C.fuse_fill_dir_t
c_fuse_gid_t = C.fuse_gid_t
c_fuse_mode_t = C.fuse_mode_t
c_fuse_off_t = C.fuse_off_t
c_fuse_opt_offset_t = C.fuse_opt_offset_t
c_enum_fuse_readdir_flags = C.enum_fuse_readdir_flags
c_fuse_stat_t = C.fuse_stat_t
c_fuse_stat_ex_t = C.fuse_stat_ex_t
c_fuse_statvfs_t = C.fuse_statvfs_t
c_fuse_timespec_t = C.fuse_timespec_t
c_fuse_uid_t = C.fuse_uid_t
c_int = C.int
c_int16_t = C.int16_t
c_int32_t = C.int32_t
c_int64_t = C.int64_t
c_int8_t = C.int8_t
c_size_t = C.size_t
c_struct_fuse = C.struct_fuse
c_struct_fuse_args = C.struct_fuse_args
c_struct_fuse_config = C.struct_fuse_config
c_struct_fuse_conn_info = C.struct_fuse_conn_info
c_struct_fuse_context = C.struct_fuse_context
c_struct_fuse_file_info = C.struct_fuse_file_info
c_struct_fuse_opt = C.struct_fuse_opt
c_uint16_t = C.uint16_t
c_uint32_t = C.uint32_t
c_uint64_t = C.uint64_t
c_uint8_t = C.uint8_t
c_uintptr_t = C.uintptr_t
c_unsigned = C.unsigned
)
func c_GoString(s *c_char) string {
@ -891,13 +882,14 @@ func c_fuse_opt_free_args(args *c_struct_fuse_args) {
func c_hostAsgnCconninfo(conn *c_struct_fuse_conn_info,
capCaseInsensitive c_bool,
capReaddirPlus c_bool,
capDeleteAccess c_bool) {
C.hostAsgnCconninfo(conn, capCaseInsensitive, capReaddirPlus, capDeleteAccess)
capDeleteAccess c_bool,
capOpenTrunc c_bool) {
C.hostAsgnCconninfo(conn, capCaseInsensitive, capReaddirPlus, capDeleteAccess, capOpenTrunc)
}
func c_hostAsgnCconfig(cfg *c_struct_fuse_config,
func c_hostAsgnCconfig(conf *c_struct_fuse_config,
directIO c_bool,
useIno c_bool) {
C.hostAsgnCconfig(cfg, directIO, useIno)
C.hostAsgnCconfig(conf, directIO, useIno)
}
func c_hostCstatvfsFromFusestatfs(stbuf *c_fuse_statvfs_t,
bsize c_uint64_t,
@ -1000,15 +992,15 @@ func c_hostOptParse(args *c_struct_fuse_args, data unsafe.Pointer, opts *c_struc
return C.hostOptParse(args, data, opts, nonopts)
}
//export go_hostGetattrFuse3
func go_hostGetattrFuse3(path0 *c_char, stat0 *c_fuse_stat_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostGetattr(path0, stat0, fi0)
//export go_hostGetattr
func go_hostGetattr(path0 *c_char, stat0 *c_fuse_stat_t) (errc0 c_int) {
return hostGetattr(path0, stat0, nil)
}
//export go_hostGetattrFuse2
func go_hostGetattrFuse2(path0 *c_char, stat0 *c_fuse_stat_t) (errc0 c_int) {
return hostGetattr(path0, stat0, nil)
//export go_hostGetattr3
func go_hostGetattr3(path0 *c_char, stat0 *c_fuse_stat_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostGetattr(path0, stat0, fi0)
}
//export go_hostReadlink
@ -1041,14 +1033,14 @@ func go_hostSymlink(target0 *c_char, newpath0 *c_char) (errc0 c_int) {
return hostSymlink(target0, newpath0)
}
//export go_hostRenameFuse3
func go_hostRenameFuse3(oldpath0 *c_char, newpath0 *c_char, flags c_uint32_t) (errc0 c_int) {
return hostRename(oldpath0, newpath0, flags)
//export go_hostRename
func go_hostRename(oldpath0 *c_char, newpath0 *c_char) (errc0 c_int) {
return hostRename(oldpath0, newpath0, 0)
}
//export go_hostRenameFuse2
func go_hostRenameFuse2(oldpath0 *c_char, newpath0 *c_char) (errc0 c_int) {
return hostRename(oldpath0, newpath0, 0)
//export go_hostRename3
func go_hostRename3(oldpath0 *c_char, newpath0 *c_char, flags c_uint32_t) (errc0 c_int) {
return hostRename(oldpath0, newpath0, flags)
}
//export go_hostLink
@ -1056,37 +1048,37 @@ func go_hostLink(oldpath0 *c_char, newpath0 *c_char) (errc0 c_int) {
return hostLink(oldpath0, newpath0)
}
//export go_hostChmodFuse3
func go_hostChmodFuse3(path0 *c_char, mode0 c_fuse_mode_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostChmod(path0, mode0, fi0)
}
//export go_hostChmodFuse2
func go_hostChmodFuse2(path0 *c_char, mode0 c_fuse_mode_t) (errc0 c_int) {
//export go_hostChmod
func go_hostChmod(path0 *c_char, mode0 c_fuse_mode_t) (errc0 c_int) {
return hostChmod(path0, mode0, nil)
}
//export go_hostChownFuse3
func go_hostChownFuse3(path0 *c_char, uid0 c_fuse_uid_t, gid0 c_fuse_gid_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostChown(path0, uid0, gid0, fi0)
//export go_hostChmod3
func go_hostChmod3(path0 *c_char, mode0 c_fuse_mode_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostChmod(path0, mode0, fi0)
}
//export go_hostChownFuse2
func go_hostChownFuse2(path0 *c_char, uid0 c_fuse_uid_t, gid0 c_fuse_gid_t) (errc0 c_int) {
//export go_hostChown
func go_hostChown(path0 *c_char, uid0 c_fuse_uid_t, gid0 c_fuse_gid_t) (errc0 c_int) {
return hostChown(path0, uid0, gid0, nil)
}
//export go_hostTruncateFuse3
func go_hostTruncateFuse3(path0 *c_char, size0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostTruncate(path0, size0, fi0)
//export go_hostChown3
func go_hostChown3(path0 *c_char, uid0 c_fuse_uid_t, gid0 c_fuse_gid_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostChown(path0, uid0, gid0, fi0)
}
//export go_hostTruncateFuse2
func go_hostTruncateFuse2(path0 *c_char, size0 c_fuse_off_t) (errc0 c_int) {
//export go_hostTruncate
func go_hostTruncate(path0 *c_char, size0 c_fuse_off_t) (errc0 c_int) {
return hostTruncate(path0, size0, nil)
}
//export go_hostTruncate3
func go_hostTruncate3(path0 *c_char, size0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostTruncate(path0, size0, fi0)
}
//export go_hostOpen
func go_hostOpen(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostOpen(path0, fi0)
@ -1150,18 +1142,18 @@ func go_hostOpendir(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostOpendir(path0, fi0)
}
//export go_hostReaddirFuse3
func go_hostReaddirFuse3(path0 *c_char,
buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, ofst0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info, flags c_fuse_readdir_flags_t) (errc0 c_int) {
return hostReaddir(path0, buff0, fill0, ofst0, fi0, flags)
}
//export go_hostReaddirFuse2
func go_hostReaddirFuse2(path0 *c_char,
//export go_hostReaddir
func go_hostReaddir(path0 *c_char,
buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, ofst0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostReaddir(path0, buff0, fill0, ofst0, fi0, 0)
return hostReaddir(path0, buff0, fill0, ofst0, fi0)
}
//export go_hostReaddir3
func go_hostReaddir3(path0 *c_char,
buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, ofst0 c_fuse_off_t,
fi0 *c_struct_fuse_file_info, flags c_enum_fuse_readdir_flags) (errc0 c_int) {
return hostReaddir(path0, buff0, fill0, ofst0, fi0)
}
//export go_hostReleasedir
@ -1174,14 +1166,14 @@ func go_hostFsyncdir(path0 *c_char, datasync c_int, fi0 *c_struct_fuse_file_info
return hostFsyncdir(path0, datasync, fi0)
}
//export go_hostInitFuse3
func go_hostInitFuse3(conn0 *c_struct_fuse_conn_info, conf0 *c_struct_fuse_config) (user_data unsafe.Pointer) {
return hostInit(conn0, conf0)
//export go_hostInit
func go_hostInit(conn0 *c_struct_fuse_conn_info) (user_data unsafe.Pointer) {
return hostInit(conn0, nil)
}
//export go_hostInitFuse2
func go_hostInitFuse2(conn0 *c_struct_fuse_conn_info) (user_data unsafe.Pointer) {
return hostInit(conn0, nil)
//export go_hostInit3
func go_hostInit3(conn0 *c_struct_fuse_conn_info, conf0 *c_struct_fuse_config) (user_data unsafe.Pointer) {
return hostInit(conn0, conf0)
}
//export go_hostDestroy
@ -1211,14 +1203,14 @@ func go_hostFgetattr(path0 *c_char, stat0 *c_fuse_stat_t,
return hostFgetattr(path0, stat0, fi0)
}
//export go_hostUtimensFuse3
func go_hostUtimensFuse3(path0 *c_char, tmsp0 *c_fuse_timespec_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostUtimens(path0, tmsp0, fi0)
//export go_hostUtimens
func go_hostUtimens(path0 *c_char, tmsp0 *c_fuse_timespec_t) (errc0 c_int) {
return hostUtimens(path0, tmsp0, nil)
}
//export go_hostUtimensFuse2
func go_hostUtimensFuse2(path0 *c_char, tmsp0 *c_fuse_timespec_t) (errc0 c_int) {
return hostUtimens(path0, tmsp0, nil)
//export go_hostUtimens3
func go_hostUtimens3(path0 *c_char, tmsp0 *c_fuse_timespec_t, fi0 *c_struct_fuse_file_info) (errc0 c_int) {
return hostUtimens(path0, tmsp0, fi0)
}
//export go_hostGetpath

View File

@ -86,26 +86,6 @@ type fuse_operations struct {
fsetattr_x uintptr
}
type fuse_readdir_flags_t struct {
st_dev c_fuse_dev_t
_ align64
st_ino c_fuse_ino_t
st_mode c_fuse_mode_t
st_nlink c_fuse_nlink_t
st_uid c_fuse_uid_t
st_gid c_fuse_gid_t
st_rdev c_fuse_dev_t
_ align64
st_size c_fuse_off_t
st_atim c_fuse_timespec_t
st_mtim c_fuse_timespec_t
st_ctim c_fuse_timespec_t
st_blksize c_fuse_blksize_t
_ align64
st_blocks c_fuse_blkcnt_t
st_birthtim c_fuse_timespec_t
}
type fuse_stat_t struct {
st_dev c_fuse_dev_t
_ align64
@ -163,31 +143,6 @@ type struct_fuse_args struct {
}
type struct_fuse_config struct {
set_gid c_int
gid c_unsigned
set_uid c_int
uid c_unsigned
set_mode c_int
umask c_unsigned
entry_timeout c_double
negative_timeout c_double
attr_timeout c_double
intr c_int
intr_signal c_int
remember c_int
hard_remove c_int
use_ino c_int
readdir_ino c_int
direct_io c_int
kernel_cache c_int
auto_cache c_int
no_rofd_flush c_int
ac_attr_timeout_set c_int
ac_attr_timeout c_double
nullpath_ok c_int
parallel_direct_writes c_int
fmask c_unsigned
dmask c_unsigned
}
type struct_fuse_conn_info struct {
@ -228,7 +183,6 @@ type struct_fuse_opt struct {
type (
c_bool = bool
c_char = byte
c_double = float64
c_fuse_blkcnt_t = int64
c_fuse_blksize_t = int32
c_fuse_dev_t = uint32
@ -242,7 +196,6 @@ type (
c_fuse_off_t = int64
c_fuse_opt_offset_t = uint32
c_fuse_pid_t = int32
c_fuse_readdir_flags_t = uintptr
c_fuse_stat_t = fuse_stat_t
c_fuse_stat_ex_t = fuse_stat_ex_t
c_fuse_statvfs_t = fuse_statvfs_t
@ -356,7 +309,8 @@ func c_fuse_opt_free_args(args *c_struct_fuse_args) {
func c_hostAsgnCconninfo(conn *c_struct_fuse_conn_info,
capCaseInsensitive c_bool,
capReaddirPlus c_bool,
capDeleteAccess c_bool) {
capDeleteAccess c_bool,
capOpenTrunc c_bool) {
conn.want |= conn.capable & FSP_FUSE_CAP_STAT_EX
cgofuse_stat_ex = 0 != conn.want&FSP_FUSE_CAP_STAT_EX // hack!
if capCaseInsensitive {
@ -369,7 +323,7 @@ func c_hostAsgnCconninfo(conn *c_struct_fuse_conn_info,
conn.want |= conn.capable & FSP_FUSE_CAP_DELETE_ACCESS
}
}
func c_hostAsgnCconfig(cfg *c_struct_fuse_config,
func c_hostAsgnCconfig(conf *c_struct_fuse_config,
directIO c_bool,
useIno c_bool) {
}
@ -839,7 +793,7 @@ func go_hostOpendir64(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 uintpt
func go_hostReaddir64(path0 *c_char,
buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, ofst0 uintptr,
fi0 *c_struct_fuse_file_info) (errc0 uintptr) {
return uintptr(int(hostReaddir(path0, buff0, fill0, c_fuse_off_t(ofst0), fi0, 0)))
return uintptr(int(hostReaddir(path0, buff0, fill0, c_fuse_off_t(ofst0), fi0)))
}
func go_hostReleasedir64(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 uintptr) {
@ -1006,7 +960,7 @@ func go_hostReaddir32(path0 *c_char,
buff0 unsafe.Pointer, fill0 c_fuse_fill_dir_t, lofst0, hofst0 uintptr,
fi0 *c_struct_fuse_file_info) (errc0 uintptr) {
return uintptr(int(hostReaddir(path0,
buff0, fill0, (c_fuse_off_t(hofst0)<<32)|c_fuse_off_t(lofst0), fi0, 0)))
buff0, fill0, (c_fuse_off_t(hofst0)<<32)|c_fuse_off_t(lofst0), fi0)))
}
func go_hostReleasedir32(path0 *c_char, fi0 *c_struct_fuse_file_info) (errc0 uintptr) {