File: directio_example_test.go

package info (click to toggle)
golang-github-hanwen-go-fuse 2.1.0%2Bgit20220822.58a7e14-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,292 kB
  • sloc: cpp: 78; sh: 43; makefile: 16
file content (89 lines) | stat: -rw-r--r-- 2,245 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2019 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 fs_test

import (
	"context"
	"fmt"
	"log"
	"syscall"
	"time"

	"github.com/hanwen/go-fuse/v2/fs"
	"github.com/hanwen/go-fuse/v2/fuse"
)

// bytesFileHandle is a file handle that carries separate content for
// each Open call
type bytesFileHandle struct {
	content []byte
}

// bytesFileHandle allows reads
var _ = (fs.FileReader)((*bytesFileHandle)(nil))

func (fh *bytesFileHandle) Read(ctx context.Context, dest []byte, off int64) (fuse.ReadResult, syscall.Errno) {
	end := off + int64(len(dest))
	if end > int64(len(fh.content)) {
		end = int64(len(fh.content))
	}

	// We could copy to the `dest` buffer, but since we have a
	// []byte already, return that.
	return fuse.ReadResultData(fh.content[off:end]), 0
}

// timeFile is a file that contains the wall clock time as ASCII.
type timeFile struct {
	fs.Inode
}

// timeFile implements Open
var _ = (fs.NodeOpener)((*timeFile)(nil))

func (f *timeFile) Open(ctx context.Context, openFlags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
	// disallow writes
	if fuseFlags&(syscall.O_RDWR|syscall.O_WRONLY) != 0 {
		return nil, 0, syscall.EROFS
	}

	// capture open time
	now := time.Now().Format(time.StampNano) + "\n"
	fh = &bytesFileHandle{
		content: []byte(now),
	}

	// Return FOPEN_DIRECT_IO so content is not cached.
	return fh, fuse.FOPEN_DIRECT_IO, 0
}

// ExampleDirectIO shows how to create a file whose contents change on
// every read.
func Example_directIO() {
	mntDir := "/tmp/x"
	root := &fs.Inode{}

	// Mount the file system
	server, err := fs.Mount(mntDir, root, &fs.Options{
		MountOptions: fuse.MountOptions{Debug: false},

		// Setup the clock file.
		OnAdd: func(ctx context.Context) {
			ch := root.NewPersistentInode(
				ctx,
				&timeFile{},
				fs.StableAttr{Mode: syscall.S_IFREG})
			root.AddChild("clock", ch, true)
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("cat %s/clock to see the time\n", mntDir)
	fmt.Printf("Unmount by calling 'fusermount -u %s'\n", mntDir)

	// Serve the file system, until unmounted by calling fusermount -u
	server.Wait()
}