forked from zach-klippenstein/adbfs
/
util.go
106 lines (93 loc) · 2.79 KB
/
util.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
package adbfs
import (
"bytes"
"fmt"
"github.com/exidler/goadb"
"os"
"github.com/hanwen/go-fuse/v2/fuse"
"github.com/hanwen/go-fuse/v2/fuse/nodefs"
)
// asFuseDirEntries reads directory entries from a goadb DirEntries and returns them as a
// list of fuse DirEntry objects.
func asFuseDirEntries(entries []*adb.DirEntry) (result []fuse.DirEntry) {
result = make([]fuse.DirEntry, len(entries))
for i, entry := range entries {
result[i] = fuse.DirEntry{
Name: entry.Name,
Mode: osFileModeToFuseFileMode(entry.Mode),
}
}
return
}
// asFuseAttr creates a fuse Attr struct that contains the information from a goadb DirEntry.
func asFuseAttr(entry *adb.DirEntry, attr *fuse.Attr) {
*attr = fuse.Attr{
Mode: osFileModeToFuseFileMode(entry.Mode),
Size: uint64(entry.Size),
Mtime: uint64(entry.ModifiedAt.Unix()),
}
}
// osFileModeToFuseFileMode converts a standard os.FileMode to the bit array used
// by the fuse package. Permissions, regular/dir modes, symlinks, and named pipes
// are the only bits that are converted.
func osFileModeToFuseFileMode(inMode os.FileMode) (outMode uint32) {
if inMode.IsRegular() {
outMode |= fuse.S_IFREG
}
if inMode.IsDir() {
outMode |= fuse.S_IFDIR
}
if inMode&os.ModeSymlink == os.ModeSymlink {
outMode |= fuse.S_IFLNK
}
if inMode&os.ModeNamedPipe == os.ModeNamedPipe {
outMode |= fuse.S_IFIFO
}
outMode |= uint32(inMode.Perm())
return
}
// newLoggingFile returns a file object that logs all operations performed on it.
func newLoggingFile(file nodefs.File, path string) nodefs.File {
return &WrappingFile{
File: file,
BeforeCall: func(f *WrappingFile, method string, args ...interface{}) interface{} {
return StartFileOperation(method, path, formatArgsListForLog(args...))
},
AfterCall: func(f *WrappingFile, call interface{}, status *fuse.Status, results ...interface{}) {
logEntry := call.(*LogEntry)
if status != nil {
logEntry.Status(fuseStatusToErrno(*status))
}
logEntry.Result(formatArgsListForLog(results...))
logEntry.FinishOperation()
},
}
}
func formatArgsListForLog(args ...interface{}) string {
if len(args) == 0 {
return ""
}
summarizeForLog(args)
var buffer bytes.Buffer
buffer.WriteRune('[')
for i, item := range args {
fmt.Fprintf(&buffer, "%#v", item)
if i < len(args)-1 {
buffer.WriteString(", ")
}
}
buffer.WriteRune(']')
return buffer.String()
}
// summarizeByteSlices replaces all elements of the passed slice that are of type []byte with
// their length and type, so for logging they neither show sensitive data nor flood the log.
func summarizeForLog(vals []interface{}) {
for i, val := range vals {
switch val := val.(type) {
case []byte:
vals[i] = fmt.Sprintf("[]byte(%d)", len(val))
case fuse.ReadResult:
vals[i] = fmt.Sprintf("fuse.ReadResult(%d)", val.Size())
}
}
}