forked from bazil/bazil
/
fuse.go
128 lines (114 loc) · 2.65 KB
/
fuse.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
package snap
import (
"fmt"
"io"
"os"
"syscall"
"bazil.org/bazil/cas/blobs"
"bazil.org/bazil/cas/chunks"
"bazil.org/bazil/fs/snap/wire"
"bazil.org/bazil/util/env"
"bazil.org/fuse"
fusefs "bazil.org/fuse/fs"
"golang.org/x/net/context"
)
// Serve this snapshot with FUSE, with this object store.
func Open(chunkStore chunks.Store, dir *wire.Dir) (fusefs.Node, error) {
manifest := dir.Manifest.ToBlob("dir")
blob, err := blobs.Open(chunkStore, manifest)
if err != nil {
return nil, err
}
r, err := NewReader(blob, dir.Align)
if err != nil {
return nil, err
}
node := fuseDir{
chunkStore: chunkStore,
reader: r,
}
return node, nil
}
type fuseDir struct {
chunkStore chunks.Store
reader *Reader
}
var _ = fusefs.Node(fuseDir{})
var _ = fusefs.NodeStringLookuper(fuseDir{})
var _ = fusefs.NodeCreater(fuseDir{})
var _ = fusefs.Handle(fuseDir{})
var _ = fusefs.HandleReadDirAller(fuseDir{})
func (d fuseDir) Attr() fuse.Attr {
return fuse.Attr{
Mode: os.ModeDir | 0555,
Nlink: 1,
Uid: env.MyUID,
Gid: env.MyGID,
}
}
const _MAX_INT64 = 9223372036854775807
func (d fuseDir) Lookup(ctx context.Context, name string) (fusefs.Node, error) {
de, err := d.reader.Lookup(name)
if err != nil {
if os.IsNotExist(err) {
return nil, fuse.ENOENT
}
return nil, fmt.Errorf("snap lookup error: %v", err)
}
switch {
case de.Type.File != nil:
manifest := de.Type.File.Manifest.ToBlob("file")
blob, err := blobs.Open(d.chunkStore, manifest)
if err != nil {
return nil, fmt.Errorf("snap file blob open error: %v", err)
}
child := fuseFile{
rat: blob,
de: de,
}
return child, nil
case de.Type.Dir != nil:
child, err := Open(d.chunkStore, de.Type.Dir)
if err != nil {
return nil, fmt.Errorf("snap dir FUSE serving error: %v", err)
}
return child, nil
default:
return nil, fmt.Errorf("unknown entry in tree, %v", de.Type.GetValue())
}
}
func (d fuseDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
var list []fuse.Dirent
it := d.reader.Iter()
var de *wire.Dirent
var err error
for {
de, err = it.Next()
if err == io.EOF {
break
}
if err != nil {
return list, fmt.Errorf("snap readdir error: %v", err)
}
fde := fuse.Dirent{
Name: de.Name,
}
if de.Type.File != nil {
fde.Type = fuse.DT_File
} else if de.Type.Dir != nil {
fde.Type = fuse.DT_Dir
}
list = append(list, fde)
}
return list, nil
}
func (d fuseDir) Create(ctx context.Context, req *fuse.CreateRequest, resp *fuse.CreateResponse) (fusefs.Node, fusefs.Handle, error) {
return nil, nil, fuse.Errno(syscall.EROFS)
}
func stat_blocks(size uint64) uint64 {
r := size / 512
if size%512 > 0 {
r++
}
return r
}