1 // glocate -- ZFS-diff-friendly locate-like utility
2 // Copyright (C) 2022-2024 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
36 func (ent *Ent) IsDir() bool {
37 return IsDir(ent.name[len(ent.name)-1])
40 func dbCommit(dbPath string, tmp *os.File) {
41 umask := syscall.Umask(0)
43 if err := os.Chmod(tmp.Name(), os.FileMode(0666&^umask)); err != nil {
46 if err := os.Rename(tmp.Name(), dbPath); err != nil {
52 dbPath := flag.String("db", "glocate.db", "Path to database")
53 doIndex := flag.Bool("index", false, "Perform indexing")
54 doUpdate := flag.String("update", "", "Update database")
55 showMachine := flag.Bool("machine", false, "Show machine friendly")
56 showTree := flag.Bool("tree", false, "Show human-friendly tree")
57 dryRun := flag.Bool("n", false, "Dry run, do not overwrite database")
58 rootPath := flag.String("root", "", "Search only that part of tree")
60 log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
63 TmpDir, err = filepath.Abs(*dbPath)
67 TmpDir = path.Dir(TmpDir)
73 dbCommit(*dbPath, tmp)
79 tmp := updateWithDiff(*dbPath, *doUpdate)
82 dbCommit(*dbPath, tmp)
87 db, err := os.Open(*dbPath)
91 entsReader := make(chan Ent, 1<<10)
92 go reader(db, entsReader)
94 entsPrinter := make(chan Ent, 1<<10)
95 printerJob := make(chan struct{})
98 printerMachine(entsPrinter)
100 printerTree(entsPrinter)
102 printerSimple(entsPrinter)
109 root = strings.Split("./"+*rootPath, "/")
113 if len(flag.Args()) > 0 {
114 pat = "*" + flag.Arg(0) + "*"
119 var namePrev []string
121 for ent := range entsReader {
122 if hasPrefix(ent.name, root) {
128 for i = 0; i < len(ent.name); i++ {
129 if i == len(namePrev) || ent.name[i] != namePrev[i] {
133 for ; i < len(ent.name); i++ {
134 matched, err = path.Match(pat,
135 strings.ToLower(strings.TrimSuffix(ent.name[i], "/")))