forked from rclone/rclone
/
fs.go
131 lines (118 loc) · 2.9 KB
/
fs.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
// FUSE main Fs
// +build linux darwin,amd64
package mount2
import (
"os"
"syscall"
"github.com/hanwen/go-fuse/v2/fuse"
"github.com/pkg/errors"
"github.com/rclone/rclone/cmd/mountlib"
"github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/log"
"github.com/rclone/rclone/vfs"
"github.com/rclone/rclone/vfs/vfsflags"
)
// FS represents the top level filing system
type FS struct {
VFS *vfs.VFS
f fs.Fs
}
// NewFS creates a pathfs.FileSystem from the fs.Fs passed in
func NewFS(f fs.Fs) *FS {
fsys := &FS{
VFS: vfs.New(f, &vfsflags.Opt),
f: f,
}
return fsys
}
// Root returns the root node
func (f *FS) Root() (node *Node, err error) {
defer log.Trace("", "")("node=%+v, err=%v", &node, &err)
root, err := f.VFS.Root()
if err != nil {
return nil, err
}
return newNode(f, root), nil
}
// SetDebug if called, provide debug output through the log package.
func (f *FS) SetDebug(debug bool) {
fs.Debugf(f.f, "SetDebug %v", debug)
}
// get the Mode from a vfs Node
func getMode(node os.FileInfo) uint32 {
Mode := node.Mode().Perm()
if node.IsDir() {
Mode |= fuse.S_IFDIR
} else {
Mode |= fuse.S_IFREG
}
return uint32(Mode)
}
// fill in attr from node
func setAttr(node vfs.Node, attr *fuse.Attr) {
Size := uint64(node.Size())
const BlockSize = 512
Blocks := (Size + BlockSize - 1) / BlockSize
modTime := node.ModTime()
// set attributes
vfs := node.VFS()
attr.Owner.Gid = vfs.Opt.UID
attr.Owner.Uid = vfs.Opt.GID
attr.Mode = getMode(node)
attr.Size = Size
attr.Nlink = 1
attr.Blocks = Blocks
// attr.Blksize = BlockSize // not supported in freebsd/darwin, defaults to 4k if not set
s := uint64(modTime.Unix())
ns := uint32(modTime.Nanosecond())
attr.Atime = s
attr.Atimensec = ns
attr.Mtime = s
attr.Mtimensec = ns
attr.Ctime = s
attr.Ctimensec = ns
//attr.Rdev
}
// fill in AttrOut from node
func setAttrOut(node vfs.Node, out *fuse.AttrOut) {
setAttr(node, &out.Attr)
out.SetTimeout(mountlib.AttrTimeout)
}
// fill in EntryOut from node
func setEntryOut(node vfs.Node, out *fuse.EntryOut) {
setAttr(node, &out.Attr)
out.SetEntryTimeout(mountlib.AttrTimeout)
out.SetAttrTimeout(mountlib.AttrTimeout)
}
// Translate errors from mountlib into Syscall error numbers
func translateError(err error) syscall.Errno {
if err == nil {
return 0
}
switch errors.Cause(err) {
case vfs.OK:
return 0
case vfs.ENOENT, fs.ErrorDirNotFound, fs.ErrorObjectNotFound:
return syscall.ENOENT
case vfs.EEXIST, fs.ErrorDirExists:
return syscall.EEXIST
case vfs.EPERM, fs.ErrorPermissionDenied:
return syscall.EPERM
case vfs.ECLOSED:
return syscall.EBADF
case vfs.ENOTEMPTY:
return syscall.ENOTEMPTY
case vfs.ESPIPE:
return syscall.ESPIPE
case vfs.EBADF:
return syscall.EBADF
case vfs.EROFS:
return syscall.EROFS
case vfs.ENOSYS, fs.ErrorNotImplemented:
return syscall.ENOSYS
case vfs.EINVAL:
return syscall.EINVAL
}
fs.Errorf(nil, "IO error: %v", err)
return syscall.EIO
}