go_sysutils/paths/funcs_fssearchcriteria.go
brent saner c6efc2d83c
v1.12.0
FIXED:
* paths: Async searching works correctly now, and is consolidated to a
  single struct for searching options for async and synchronous
  searches.
2024-11-18 17:36:14 -05:00

126 lines
2.6 KiB
Go

package paths
import (
`io/fs`
`os`
`path/filepath`
`time`
`github.com/djherbis/times`
`r00t2.io/goutils/bitmask`
)
/*
Match returns match (a ptr to a FsSearchResult if the specified path matches, otherwise nil),
miss (ptr the specified path does not match, otherwise nil), and an fs.DirEntry and fs.FileInfo
for path. d and/or fi may be nil.
If err is not nil, it represents an unexpected error and as such, both match and miss should be nil.
Match, miss, and err will all be nil if the filesystem object/path does not exist.
*/
func (f *FsSearchCriteria) Match(path string, d fs.DirEntry, fi fs.FileInfo) (match, miss *FsSearchResult, err error) {
var typeMode fs.FileMode
var m FsSearchResult
var typeFilter *bitmask.MaskBit = bitmask.NewMaskBitExplicit(uint(f.TargetType))
m = FsSearchResult{
Path: path,
DirEntry: d,
FileInfo: fi,
Criteria: f,
}
if f == nil {
return
}
// A DirEntry can be created from a FileInfo but not vice versa.
if m.FileInfo == nil {
if m.DirEntry != nil {
if m.FileInfo, err = m.DirEntry.Info(); err != nil {
err = filterNoFileDir(err)
if err != nil {
return
}
}
} else {
if f.FollowSymlinks {
if m.FileInfo, err = os.Stat(path); err != nil {
err = filterNoFileDir(err)
if err != nil {
return
}
}
} else {
if m.FileInfo, err = os.Lstat(path); err != nil {
err = filterNoFileDir(err)
if err != nil {
return
}
}
}
m.DirEntry = fs.FileInfoToDirEntry(m.FileInfo)
}
}
if m.DirEntry == nil {
m.DirEntry = fs.FileInfoToDirEntry(m.FileInfo)
}
if m.DirEntry == nil || m.FileInfo == nil {
m.MissReason = MissNoMeta
miss = &m
return
}
if m.Times, err = times.Stat(path); err != nil {
err = filterNoFileDir(err)
if err != nil {
return
}
}
if f.PathPtrn != nil && !f.PathPtrn.MatchString(path) {
m.MissReason = MissBadPath
miss = &m
return
}
if f.BasePtrn != nil && !f.BasePtrn.MatchString(filepath.Base(path)) {
m.MissReason = MissBadBase
miss = &m
return
}
// age
if f.Age != nil {
if f.Now == nil {
f.Now = new(time.Time)
*f.Now = time.Now()
}
if !filterTimes(m.Times, f.Age, &f.AgeType, f.OlderThan, f.Now) {
m.MissReason = MissBadTime
miss = &m
return
}
}
// fs object type (file, dir, etc.)
typeMode = m.FileInfo.Mode().Type()
if typeMode == 0 && f.NoFiles {
m.MissReason = MissFile
miss = &m
return
} else if typeMode != 0 {
if !typeFilter.HasFlag(bitmask.MaskBit(typeMode)) {
m.MissReason = MissType
miss = &m
return
}
}
// If it gets to here, it matches.
match = &m
return
}