Skip to content

Commit

Permalink
Merge branch 'add-fuse3-linux' of https://github.com/jfantinhardesty/…
Browse files Browse the repository at this point in the history
…cgofuse into jfantinhardesty-add-fuse3-linux
  • Loading branch information
billziss-gh committed Jan 3, 2025
2 parents f87f5db + 6e7a97a commit 1bbc1ac
Show file tree
Hide file tree
Showing 13 changed files with 523 additions and 172 deletions.
89 changes: 52 additions & 37 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
GOARCH: ${{ matrix.arch }}
CGO_ENABLED: ${{ matrix.cgo }}
CPATH: ${{ matrix.cpath }}
GODEBUG: cgocheck=2
GOEXPERIMENT: cgocheck2
strategy:
matrix:
include:
Expand All @@ -26,33 +26,36 @@ jobs:
- os: windows-latest
arch: amd64
cgo: 0
- os: windows-latest
arch: 386
cgo: 0
- os: ubuntu-latest
arch: amd64
cgo: 1
- os: macos-10.15
- os: macos-latest
arch: amd64
cgo: 1
fail-fast: false

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
submodules: recursive

- name: Install go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
stable: true
go-version: 1.17.*
go-version: '1.23'

- name: Install winfsp and winfsp-tests (Windows)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: runner.os == 'Windows'
run: |
$releases = Invoke-WebRequest https://api.github.com/repos/winfsp/winfsp/releases | `
$headers = @{
Authorization = "token $env:GITHUB_TOKEN"
"User-Agent" = "GitHub Actions"
}
$releases = Invoke-WebRequest https://api.github.com/repos/winfsp/winfsp/releases -Headers $headers | `
ConvertFrom-Json
$asseturi = $releases[0].assets.browser_download_url | `
Expand All @@ -69,8 +72,7 @@ jobs:
- name: Install FUSE and secfs.test (Linux)
if: runner.os == 'Linux'
run: |
sudo apt-get -qq install libfuse-dev
sudo apt-get -qq install libacl1-dev
sudo apt-get -qq install libfuse-dev libfuse3-dev libacl1-dev
git clone -q https://github.com/billziss-gh/secfs.test.git secfs.test
git -C secfs.test checkout -q edf5eb4a108bfb41073f765aef0cdd32bb3ee1ed
Expand All @@ -86,37 +88,21 @@ jobs:
rm -rf secfs.test/fstest/fstest/tests/xacl
rm -rf secfs.test/fstest/fstest/tests/zzz_ResourceFork
- name: Install FUSE and secfs.test (macOS)
- name: Install FUSE (macOS)
if: runner.os == 'macOS'
run: |
# requires macos-10.15; does not work on macos-latest
# see https://github.com/actions/virtual-environments/issues/4731
brew install macfuse
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
- 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
- name: Test file systems (Windows)
- name: Test file systems (Windows) with fuse2
if: runner.os == 'Windows'
run: |
Set-PSDebug -Trace 1
Expand All @@ -134,8 +120,8 @@ jobs:
Start-Sleep 3
Pop-Location
- name: Test file systems (Linux / macOS)
if: runner.os == 'Linux' || runner.os == 'macOS'
- name: Test file systems (Linux) with fuse2
if: runner.os == 'Linux'
run: |
set -x
Expand All @@ -156,3 +142,32 @@ jobs:
rm -rf p
rmdir mnt
- name: Build packages with fuse3 (Linux)
if: runner.os == 'Linux'
run: |
go build -tags=fuse3 -v -o . ./...
go test -v -count=1 ./fuse
- name: Test file systems (Linux) with fuse3
if: runner.os == 'Linux'
run: |
set -x
mkdir p mnt
sudo ./memfs -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)
(cd mnt && ../secfs.test/tools/bin/fsx -N 10000 test xxxxxx)
sudo umount mnt
rm -rf p
rmdir mnt
3 changes: 1 addition & 2 deletions examples/hellofs/hellofs.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ 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)
Expand Down
24 changes: 18 additions & 6 deletions examples/memfs/memfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"os"
"strings"
"sync"
"unicode/utf8"

"github.com/winfsp/cgofuse/examples/shared"
"github.com/winfsp/cgofuse/fuse"
Expand Down Expand Up @@ -230,7 +231,7 @@ func (self *Memfs) Utimens(path string, tmsp []fuse.Timespec) (errc int) {
return -fuse.ENOENT
}
node.stat.Ctim = fuse.Now()
if nil == tmsp {
if tmsp == nil || (len(tmsp) == 2 && tmsp[0].Sec == 0 && tmsp[1].Sec == 0) {
tmsp0 := node.stat.Ctim
tmsa := [2]fuse.Timespec{tmsp0, tmsp0}
tmsp = tmsa[:]
Expand All @@ -243,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)
return self.openNode(path, false, flags)
}

func (self *Memfs) Getattr(path string, stat *fuse.Stat_t, fh uint64) (errc int) {
Expand Down Expand Up @@ -319,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)
return self.openNode(path, true, 0)
}

func (self *Memfs) Readdir(path string,
Expand Down Expand Up @@ -463,7 +464,7 @@ func (self *Memfs) lookupNode(path string, ancestor *node_t) (prnt *node_t, name
node = self.root
for _, c := range split(path) {
if "" != c {
if 255 < len(c) {
if 255 < utf8.RuneCountInString(c) {
panic(fuse.Error(-fuse.ENAMETOOLONG))
}
prnt, name = node, c
Expand Down Expand Up @@ -525,7 +526,7 @@ func (self *Memfs) removeNode(path string, dir bool) int {
return 0
}

func (self *Memfs) openNode(path string, dir bool) (int, uint64) {
func (self *Memfs) openNode(path string, dir bool, flags int) (int, uint64) {
_, _, node := self.lookupNode(path, nil)
if nil == node {
return -fuse.ENOENT, ^uint64(0)
Expand All @@ -536,6 +537,13 @@ func (self *Memfs) openNode(path string, dir bool) (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
Expand All @@ -545,9 +553,12 @@ func (self *Memfs) openNode(path string, dir bool) (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, node.stat.Ino)
delete(self.openmap, fh)
}
return 0
}
Expand Down Expand Up @@ -585,5 +596,6 @@ func main() {
memfs := NewMemfs()
host := fuse.NewFileSystemHost(memfs)
host.SetCapReaddirPlus(true)
host.SetUseIno(true)
host.Mount("", os.Args[1:])
}
2 changes: 2 additions & 0 deletions examples/passthrough/passthrough.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build darwin || freebsd || netbsd || openbsd || linux
// +build darwin freebsd netbsd openbsd linux

/*
Expand Down Expand Up @@ -264,5 +265,6 @@ func main() {
args = append(args[:len(args)-2], args[len(args)-1])
}
_host = fuse.NewFileSystemHost(&ptfs)
_host.SetUseIno(true)
_host.Mount("", args[1:])
}
1 change: 1 addition & 0 deletions examples/passthrough/port_darwin.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build darwin
// +build darwin

/*
Expand Down
1 change: 1 addition & 0 deletions examples/passthrough/port_freebsd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build freebsd
// +build freebsd

/*
Expand Down
1 change: 1 addition & 0 deletions examples/passthrough/port_linux.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build linux
// +build linux

/*
Expand Down
1 change: 1 addition & 0 deletions examples/passthrough/port_netbsd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build netbsd
// +build netbsd

/*
Expand Down
1 change: 1 addition & 0 deletions examples/passthrough/port_openbsd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build openbsd
// +build openbsd

/*
Expand Down
23 changes: 23 additions & 0 deletions fuse/fsop.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

// Package fuse allows the creation of user mode file systems in Go.
//
// This packages supports both FUSE2 and FUSE3 on Linux and FUSE2 on Windows and macOS.
// By default, cgofuse will link with FUSE2. To link with FUSE3, simply add '-tags=fuse3'
// to your 'go build' flags.
//
// A user mode file system is a user mode process that receives file system operations
// from the OS FUSE layer and satisfies them in user mode. A user mode file system
// implements the interface FileSystemInterface either directly or by embedding a
Expand Down Expand Up @@ -309,6 +313,25 @@ 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
Expand Down
Loading

0 comments on commit 1bbc1ac

Please sign in to comment.