forked from zach-klippenstein/adbfs
/
adb_file.go
99 lines (77 loc) · 2.7 KB
/
adb_file.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
package adbfs
import (
"fmt"
"io"
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
)
type AdbFileOpenOptions struct {
Flags FileOpenFlags
FileBuffer *FileBuffer
}
/*
AdbFile is a nodefs.File that is backed by a file on an adb device.
There is one AdbFile for each file descriptor. All AdbFiles that point to the same
path are backed by the same FileBuffer.
Note: On OSX at least, the OS will automatically map multiple open files to a single AdbFile.
*/
type AdbFile struct {
nodefs.File
AdbFileOpenOptions
}
var _ nodefs.File = &AdbFile{}
// NewAdbFile returns a File that reads and writes to name on the device.
// perms should be set from the existing file if it exists, or to the desired new permissions if new.
func NewAdbFile(opts AdbFileOpenOptions) nodefs.File {
logEntry := StartFileOperation("New", opts.FileBuffer.Path, fmt.Sprint(opts))
defer logEntry.FinishOperation()
adbFile := &AdbFile{
// Log all the operations we don't implement.
File: newLoggingFile(nodefs.NewDefaultFile(), opts.FileBuffer.Path),
AdbFileOpenOptions: opts,
}
return nodefs.NewReadOnlyFile(adbFile)
}
func (f *AdbFile) startFileOperation(name string, args string) *LogEntry {
return StartFileOperation(name, f.FileBuffer.Path, args)
}
func (f *AdbFile) InnerFile() nodefs.File {
return f.File
}
func (f *AdbFile) Release() {
logEntry := f.startFileOperation("Release", "")
defer logEntry.FinishOperation()
// Cleanup the underlying buffer after the last open file is closed.
f.FileBuffer.DecRefCount()
}
func (f *AdbFile) Read(buf []byte, off int64) (fuse.ReadResult, fuse.Status) {
logEntry := f.startFileOperation("Read", formatArgsListForLog(buf, off))
defer logEntry.FinishOperation()
if !f.Flags.CanRead() {
// This is not a user-permission denial, it's a filesystem config denial, so don't use EACCES.
return readError(ErrNotPermitted, logEntry)
}
n, err := f.FileBuffer.ReadAt(buf, off)
if err == io.EOF {
err = nil
}
if err != nil {
return readError(err, logEntry)
}
logEntry.Result("read %d bytes", n)
return fuse.ReadResultData(buf[:n]), toFuseStatusLog(OK, logEntry)
}
// Fsync re-reads the file from the device into memory.
func (f *AdbFile) Fsync(flags int) fuse.Status {
logEntry := f.startFileOperation("Fsync", formatArgsListForLog(flags))
defer logEntry.FinishOperation()
err := f.FileBuffer.Sync(logEntry)
return toFuseStatusLog(err, logEntry)
}
func (f *AdbFile) GetAttr(out *fuse.Attr) fuse.Status {
logEntry := f.startFileOperation("GetAttr", "")
defer logEntry.FinishOperation()
// This operation doesn't require a read flag.
err := getAttr(f.FileBuffer.Path, f.FileBuffer.Client, logEntry, out)
return toFuseStatusLog(err, logEntry)
}