adbfm/adb.go

226 lines
4.4 KiB
Go
Raw Permalink Normal View History

2020-11-10 20:35:36 +00:00
package main
2020-01-24 23:02:09 +00:00
import (
"errors"
"fmt"
2020-08-18 10:53:24 +00:00
"io/ioutil"
2020-01-24 23:02:09 +00:00
"log"
2020-04-09 02:54:56 +00:00
"os"
2020-08-18 10:53:24 +00:00
"path"
2020-04-09 02:54:56 +00:00
"sort"
"strings"
2020-01-24 23:02:09 +00:00
"sync"
2020-09-08 22:54:10 +00:00
"time"
2020-01-24 23:02:09 +00:00
adb "github.com/zach-klippenstein/goadb"
)
// DefaultPort is the default port the ADB server listens on.
const DefaultPort = 5037
2020-11-10 20:35:36 +00:00
// adbConn represents a connection with an ADB server.
type adbConn struct {
2020-01-24 23:02:09 +00:00
bridge *adb.Adb
device *adb.Device
2020-08-18 10:53:24 +00:00
dir string
2020-01-24 23:02:09 +00:00
2020-08-18 10:53:24 +00:00
sync.Mutex
2020-01-24 23:02:09 +00:00
}
// connectBridge establishes a connection with an ADB server. When host and
// port are unspecified they are replaced with localhost and the default port.
func connectBridge(host string, port int, pathToADB string) (bridge *adbConn, err error) {
2020-10-03 00:30:24 +00:00
adbBridge, err := adb.NewWithConfig(adb.ServerConfig{
2020-01-24 23:02:09 +00:00
PathToAdb: pathToADB,
Host: host,
Port: port,
})
if err != nil {
log.Fatal(err)
}
2020-10-03 00:30:24 +00:00
adbBridge.StartServer() // Ignore error
2020-01-24 23:02:09 +00:00
2020-10-03 00:30:24 +00:00
_, err = adbBridge.ServerVersion()
2020-01-24 23:02:09 +00:00
if err != nil {
return nil, fmt.Errorf("failed to get server version: %s", err)
}
2020-11-10 20:35:36 +00:00
return &adbConn{bridge: adbBridge}, nil
2020-01-24 23:02:09 +00:00
}
func (a *adbConn) connectDevice(host string, port int) (err error) {
return a.bridge.Connect(host, port)
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) listDevices() (devices []*adb.DeviceInfo, err error) {
2020-01-24 23:02:09 +00:00
a.Lock()
defer a.Unlock()
deviceInfoList, err := a.bridge.ListDevices()
if err != nil {
return nil, err
}
for _, deviceInfo := range deviceInfoList {
devices = append(devices, deviceInfo)
}
return devices, nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) setDevice(deviceInfo *adb.DeviceInfo) (err error) {
2020-01-24 23:02:09 +00:00
a.Lock()
defer a.Unlock()
device := a.bridge.Device(adb.DeviceWithSerial(deviceInfo.Serial))
if device == nil {
return fmt.Errorf("failed to get device with serial %s", deviceInfo.Serial)
}
a.device = device
return nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) upload(fileName string, data []byte, mtime time.Time) (err error) {
2020-08-18 10:53:24 +00:00
a.Lock()
defer a.Unlock()
2020-09-08 22:54:10 +00:00
writer, err := a.device.OpenWrite(path.Join(a.dir, fileName), 0655, mtime)
if err != nil {
return fmt.Errorf("failed to open remote file: %s", err)
}
defer writer.Close()
n, err := writer.Write(data)
if err != nil {
return err
} else if n != len(data) {
return errors.New("failed to write file")
}
return nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) download(fileName string) (data []byte, err error) {
2020-09-08 22:54:10 +00:00
a.Lock()
defer a.Unlock()
reader, err := a.device.OpenRead(path.Join(a.dir, fileName))
2020-08-18 10:53:24 +00:00
if err != nil {
return nil, err
}
2020-09-08 22:54:10 +00:00
defer reader.Close()
2020-08-18 10:53:24 +00:00
2020-10-03 00:30:24 +00:00
data, err = ioutil.ReadAll(reader)
2020-08-18 10:53:24 +00:00
if err != nil {
return nil, err
}
return data, nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) directoryEntries(dir string) (entries []*adb.DirEntry, err error) {
2020-01-24 23:02:09 +00:00
a.Lock()
defer a.Unlock()
if a.device == nil {
return nil, errors.New("no device")
}
2020-08-18 10:53:24 +00:00
a.dir = dir
listEntries, err := a.device.ListDirEntries(dir)
2020-01-24 23:02:09 +00:00
if err != nil {
return nil, fmt.Errorf("failed to get dirents: %s", err)
}
for listEntries.Next() {
2020-04-09 02:54:56 +00:00
entry := listEntries.Entry()
if entry.Name == "." {
continue
}
entries = append(entries, entry)
2020-01-24 23:02:09 +00:00
}
if listEntries.Err() != nil {
return nil, fmt.Errorf("failed to list files: %s", err)
}
2020-04-09 02:54:56 +00:00
sort.Slice(entries, func(i, j int) bool {
if entries[i].Name == ".." {
return true
} else if (entries[i].Mode&os.ModeDir != 0) != (entries[j].Mode&os.ModeDir != 0) {
return entries[i].Mode&os.ModeDir != 0
}
return strings.ToLower(entries[i].Name) < strings.ToLower(entries[j].Name)
})
2020-01-24 23:02:09 +00:00
return entries, nil
}
2020-10-03 00:30:24 +00:00
func (a *adbConn) copy(old string, new string) (err error) {
a.Lock()
defer a.Unlock()
if a.device == nil {
return errors.New("no device")
}
_, err = a.device.RunCommand("cp", "-R", old, new)
if err != nil {
return fmt.Errorf("failed to copy file: %s", err)
}
return nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) move(old string, new string) (err error) {
2020-10-03 00:30:24 +00:00
a.Lock()
defer a.Unlock()
if a.device == nil {
return errors.New("no device")
}
_, err = a.device.RunCommand("mv", old, new)
if err != nil {
return fmt.Errorf("failed to move file: %s", err)
}
return nil
}
2020-11-10 20:35:36 +00:00
2020-11-10 21:04:45 +00:00
func (a *adbConn) delete(path string) (err error) {
a.Lock()
defer a.Unlock()
if a.device == nil {
return errors.New("no device")
}
_, err = a.device.RunCommand("rm", "-rf", path)
if err != nil {
return fmt.Errorf("failed to delete file or directory: %s", err)
}
return nil
}
2020-11-10 20:35:36 +00:00
func (a *adbConn) newDirectory(path string) (err error) {
a.Lock()
defer a.Unlock()
if a.device == nil {
return errors.New("no device")
}
_, err = a.device.RunCommand("mkdir", path)
if err != nil {
return fmt.Errorf("failed to create directory: %s", err)
}
return nil
}