package goadb import ( "fmt" "os" "time" "github.com/zach-klippenstein/goadb/wire" ) // DirEntry holds information about a directory entry on a device. type DirEntry struct { Name string Mode os.FileMode Size int32 ModifiedAt time.Time } // DirEntries iterates over directory entries. type DirEntries struct { scanner wire.SyncScanner currentEntry *DirEntry err error } // ReadAllDirEntries reads all the remaining directory entries into a slice, // closes self, and returns any error. // If err is non-nil, result will contain any entries read until the error occurred. func (entries *DirEntries) ReadAll() (result []*DirEntry, err error) { defer entries.Close() for entries.Next() { result = append(result, entries.Entry()) } err = entries.Err() return } func (entries *DirEntries) Next() bool { if entries.err != nil { return false } entry, done, err := readNextDirListEntry(entries.scanner) if err != nil { entries.err = err entries.Close() return false } entries.currentEntry = entry if done { entries.Close() return false } return true } func (entries *DirEntries) Entry() *DirEntry { return entries.currentEntry } func (entries *DirEntries) Err() error { return entries.err } // Close closes the connection to the adb. // Next() will call Close() before returning false. func (entries *DirEntries) Close() error { return entries.scanner.Close() } func readNextDirListEntry(s wire.SyncScanner) (entry *DirEntry, done bool, err error) { id, err := s.ReadOctetString() if err != nil { return } if id == "DONE" { done = true return } else if id != "DENT" { err = fmt.Errorf("error reading dir entries: expected dir entry ID 'DENT', but got '%s'", id) return } mode, err := s.ReadFileMode() if err != nil { err = fmt.Errorf("error reading dir entries: error reading file mode: %v", err) return } size, err := s.ReadInt32() if err != nil { err = fmt.Errorf("error reading dir entries: error reading file size: %v", err) return } mtime, err := s.ReadTime() if err != nil { err = fmt.Errorf("error reading dir entries: error reading file time: %v", err) return } name, err := s.ReadString() if err != nil { err = fmt.Errorf("error reading dir entries: error reading file name: %v", err) return } done = false entry = &DirEntry{ Name: name, Mode: mode, Size: size, ModifiedAt: mtime, } return }