-
Notifications
You must be signed in to change notification settings - Fork 86
/
notifyfs.go
134 lines (120 loc) · 3.03 KB
/
notifyfs.go
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//go:build windows
// +build windows
/*
* notifyfs.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 (
"fmt"
"os"
"strconv"
"sync/atomic"
"time"
"github.com/winfsp/cgofuse/fuse"
)
type Notifyfs struct {
fuse.FileSystemBase
ticks uint64
}
func countFromTicks(ticks uint64) uint64 {
/*
* The formula below produces the periodic sequence:
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
* ...
*/
div10 := (ticks % 20) / 10
mod10 := ticks % 10
mdv10 := 1 - div10
mmd10 := 10 - mod10
return mdv10*mod10 + div10*mmd10
}
func (self *Notifyfs) count() uint64 {
return countFromTicks(atomic.LoadUint64(&self.ticks))
}
func (self *Notifyfs) lookup(path string) uint64 {
count := self.count()
index, _ := strconv.ParseUint(path[1:], 10, 0)
if 0 < index && index <= count {
return index
}
return ^uint64(0)
}
func (self *Notifyfs) Open(path string, flags int) (errc int, fh uint64) {
index := self.lookup(path)
if ^uint64(0) == index {
return -fuse.ENOENT, ^uint64(0)
}
return 0, index
}
func (self *Notifyfs) Getattr(path string, stat *fuse.Stat_t, fh uint64) (errc int) {
if "/" == path {
stat.Mode = fuse.S_IFDIR | 0555
return 0
}
index := self.lookup(path)
if ^uint64(0) == index {
return -fuse.ENOENT
}
contents := strconv.FormatUint(index, 10) + "\n"
stat.Mode = fuse.S_IFREG | 0444
stat.Size = int64(len(contents))
return 0
}
func (self *Notifyfs) Read(path string, buff []byte, ofst int64, fh uint64) (n int) {
index := self.lookup(path)
if ^uint64(0) == index {
return -fuse.ENOENT
}
contents := strconv.FormatUint(index, 10) + "\n"
endofst := ofst + int64(len(buff))
if endofst > int64(len(contents)) {
endofst = int64(len(contents))
}
if endofst < ofst {
return 0
}
n = copy(buff, contents[ofst:endofst])
return
}
func (self *Notifyfs) Readdir(path string,
fill func(name string, stat *fuse.Stat_t, ofst int64) bool,
ofst int64,
fh uint64) (errc int) {
fill(".", nil, 0)
fill("..", nil, 0)
count := self.count()
for u := uint64(1); count >= u; u++ {
fill(strconv.FormatUint(u, 10), nil, 0)
}
return 0
}
func (self *Notifyfs) tick(host *fuse.FileSystemHost) {
ticker := time.NewTicker(1 * time.Second)
for range ticker.C {
ticks := atomic.AddUint64(&self.ticks, 1)
oldcount := countFromTicks(ticks - 1)
newcount := countFromTicks(ticks)
if oldcount < newcount {
fmt.Println("CREATE", "/"+strconv.FormatUint(newcount, 10))
host.Notify("/"+strconv.FormatUint(newcount, 10), fuse.NOTIFY_CREATE)
} else if oldcount > newcount {
fmt.Println("UNLINK", "/"+strconv.FormatUint(oldcount, 10))
host.Notify("/"+strconv.FormatUint(oldcount, 10), fuse.NOTIFY_UNLINK)
}
}
}
func main() {
notifyfs := &Notifyfs{}
host := fuse.NewFileSystemHost(notifyfs)
go notifyfs.tick(host)
host.Mount("", os.Args[1:])
}