github.com/ratrocket/u-root@v0.0.0-20180201221235-1cf9f48ee2cf/pkg/find/find.go (about) 1 // Copyright 2015-2017 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package find 6 7 import ( 8 "os" 9 "path/filepath" 10 ) 11 12 type Name struct { 13 Name string 14 os.FileInfo 15 Err error 16 } 17 18 type Finder struct { 19 Root string 20 Pattern string 21 Match func(string, string) (bool, error) 22 Mode os.FileMode 23 ModeMask os.FileMode 24 Debug func(string, ...interface{}) 25 Names chan *Name 26 } 27 28 type Set func(f *Finder) error 29 30 func New(opts ...Set) (*Finder, error) { 31 // All of these can be overridden by the opts 32 var f = &Finder{Root: "/"} 33 f.Debug = func(string, ...interface{}) {} 34 f.Names = make(chan *Name, 128) 35 f.Match = filepath.Match 36 for _, opt := range opts { 37 if err := opt(f); err != nil { 38 return nil, err 39 } 40 } 41 f.Debug("Create new Finder: %v", f) 42 return f, nil 43 } 44 45 func (f *Finder) Find() { 46 filepath.Walk(f.Root, func(n string, fi os.FileInfo, err error) error { 47 if err != nil { 48 f.Names <- &Name{Name: n, Err: err} 49 return nil 50 } 51 // If it matches, then push its name into the result channel, 52 // and keep looking. 53 f.Debug("Check Pattern '%q' against name '%q'", f.Pattern, fi.Name()) 54 if f.Pattern != "" { 55 m, err := f.Match(f.Pattern, fi.Name()) 56 if err != nil { 57 f.Debug("%s: err on matching: %v", fi.Name(), err) 58 return nil 59 } 60 if !m { 61 f.Debug("%s: name does not match", fi.Name()) 62 return nil 63 } 64 } 65 m := fi.Mode() 66 f.Debug("%s fi.Mode %v f.ModeMask %v f.Mode %v", n, m, f.ModeMask, fi.Mode) 67 if (m & f.ModeMask) != f.Mode { 68 f.Debug("%s: Mode does not match", n) 69 return nil 70 } 71 f.Debug("Found: %v", n) 72 f.Names <- &Name{Name: n, FileInfo: fi} 73 return nil 74 }) 75 close(f.Names) 76 }