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  }